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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2014-2015 Edmund Huber
  3. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  4. // released under the MIT license
  5. package irc
  6. import (
  7. "bufio"
  8. "context"
  9. "crypto/tls"
  10. "encoding/base64"
  11. "fmt"
  12. "log"
  13. "math/rand"
  14. "net"
  15. "net/http"
  16. "os"
  17. "os/signal"
  18. "strconv"
  19. "strings"
  20. "sync"
  21. "syscall"
  22. "time"
  23. "github.com/goshuirc/irc-go/ircfmt"
  24. "github.com/goshuirc/irc-go/ircmsg"
  25. "github.com/oragono/oragono/irc/caps"
  26. "github.com/oragono/oragono/irc/logger"
  27. "github.com/oragono/oragono/irc/sno"
  28. "github.com/tidwall/buntdb"
  29. )
  30. var (
  31. // common error line to sub values into
  32. errorMsg, _ = (&[]ircmsg.IrcMessage{ircmsg.MakeMessage(nil, "", "ERROR", "%s ")}[0]).Line()
  33. // common error responses
  34. couldNotParseIPMsg, _ = (&[]ircmsg.IrcMessage{ircmsg.MakeMessage(nil, "", "ERROR", "Unable to parse your IP address")}[0]).Line()
  35. )
  36. const (
  37. // when shutting down the REST server, wait this long
  38. // before killing active connections. TODO: this might not be
  39. // necessary at all? but it seems prudent to avoid potential resource
  40. // leaks
  41. httpShutdownTimeout = time.Second
  42. )
  43. // Limits holds the maximum limits for various things such as topic lengths.
  44. type Limits struct {
  45. AwayLen int
  46. ChannelLen int
  47. KickLen int
  48. MonitorEntries int
  49. NickLen int
  50. TopicLen int
  51. ChanListModes int
  52. LineLen LineLenLimits
  53. }
  54. // LineLenLimits holds the maximum limits for IRC lines.
  55. type LineLenLimits struct {
  56. Tags int
  57. Rest int
  58. }
  59. // ListenerWrapper wraps a listener so it can be safely reconfigured or stopped
  60. type ListenerWrapper struct {
  61. listener net.Listener
  62. tlsConfig *tls.Config
  63. shouldStop bool
  64. // lets the ListenerWrapper inform the server that it has stopped:
  65. stopEvent chan bool
  66. // protects atomic update of tlsConfig and shouldStop:
  67. configMutex sync.Mutex
  68. }
  69. // Server is the main Oragono server.
  70. type Server struct {
  71. accountAuthenticationEnabled bool
  72. accountRegistration *AccountRegistration
  73. accounts map[string]*ClientAccount
  74. channelRegistrationEnabled bool
  75. channels ChannelNameMap
  76. channelJoinPartMutex sync.Mutex // used when joining/parting channels to prevent stomping over each others' access and all
  77. checkIdent bool
  78. clients *ClientLookupSet
  79. commands chan Command
  80. configFilename string
  81. configurableStateMutex sync.RWMutex // generic protection for server state modified by rehash()
  82. connectionLimits *ConnectionLimits
  83. connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
  84. connectionThrottle *ConnectionThrottle
  85. connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
  86. ctime time.Time
  87. defaultChannelModes Modes
  88. dlines *DLineManager
  89. isupport *ISupportList
  90. klines *KLineManager
  91. limits Limits
  92. listeners map[string]*ListenerWrapper
  93. logger *logger.Manager
  94. MaxSendQBytes uint64
  95. monitorManager *MonitorManager
  96. motdLines []string
  97. name string
  98. nameCasefolded string
  99. networkName string
  100. newConns chan clientConn
  101. operators map[string]Oper
  102. operclasses map[string]OperClass
  103. password []byte
  104. passwords *PasswordManager
  105. registeredChannels map[string]*RegisteredChannel
  106. registeredChannelsMutex sync.RWMutex
  107. rehashMutex sync.Mutex
  108. rehashSignal chan os.Signal
  109. restAPI RestAPIConfig
  110. restAPIServer *http.Server
  111. proxyAllowedFrom []string
  112. signals chan os.Signal
  113. snomasks *SnoManager
  114. store *buntdb.DB
  115. stsEnabled bool
  116. whoWas *WhoWasList
  117. }
  118. var (
  119. // ServerExitSignals are the signals the server will exit on.
  120. ServerExitSignals = []os.Signal{
  121. syscall.SIGINT,
  122. syscall.SIGTERM,
  123. syscall.SIGQUIT,
  124. }
  125. )
  126. type clientConn struct {
  127. Conn net.Conn
  128. IsTLS bool
  129. }
  130. // NewServer returns a new Oragono server.
  131. func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
  132. // TODO move this to main?
  133. if err := GenerateHelpIndices(); err != nil {
  134. return nil, err
  135. }
  136. // initialize data structures
  137. server := &Server{
  138. accounts: make(map[string]*ClientAccount),
  139. channels: *NewChannelNameMap(),
  140. clients: NewClientLookupSet(),
  141. commands: make(chan Command),
  142. listeners: make(map[string]*ListenerWrapper),
  143. logger: logger,
  144. monitorManager: NewMonitorManager(),
  145. newConns: make(chan clientConn),
  146. registeredChannels: make(map[string]*RegisteredChannel),
  147. rehashSignal: make(chan os.Signal, 1),
  148. signals: make(chan os.Signal, len(ServerExitSignals)),
  149. snomasks: NewSnoManager(),
  150. whoWas: NewWhoWasList(config.Limits.WhowasEntries),
  151. }
  152. if err := server.applyConfig(config, true); err != nil {
  153. return nil, err
  154. }
  155. // Attempt to clean up when receiving these signals.
  156. signal.Notify(server.signals, ServerExitSignals...)
  157. signal.Notify(server.rehashSignal, syscall.SIGHUP)
  158. return server, nil
  159. }
  160. // setISupport sets up our RPL_ISUPPORT reply.
  161. func (server *Server) setISupport() {
  162. maxTargetsString := strconv.Itoa(maxTargets)
  163. server.configurableStateMutex.RLock()
  164. // add RPL_ISUPPORT tokens
  165. isupport := NewISupportList()
  166. isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
  167. isupport.Add("CASEMAPPING", casemappingName)
  168. isupport.Add("CHANMODES", strings.Join([]string{Modes{BanMask, ExceptMask, InviteMask}.String(), "", Modes{UserLimit, Key}.String(), Modes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret}.String()}, ","))
  169. isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
  170. isupport.Add("CHANTYPES", "#")
  171. isupport.Add("ELIST", "U")
  172. isupport.Add("EXCEPTS", "")
  173. isupport.Add("INVEX", "")
  174. isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
  175. isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(server.limits.ChanListModes)))
  176. isupport.Add("MAXTARGETS", maxTargetsString)
  177. isupport.Add("MODES", "")
  178. isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
  179. isupport.Add("NETWORK", server.networkName)
  180. isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
  181. isupport.Add("PREFIX", "(qaohv)~&@%+")
  182. isupport.Add("RPCHAN", "E")
  183. isupport.Add("RPUSER", "E")
  184. isupport.Add("STATUSMSG", "~&@%+")
  185. isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:%s,TAGMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString, maxTargetsString))
  186. isupport.Add("TOPICLEN", strconv.Itoa(server.limits.TopicLen))
  187. // account registration
  188. if server.accountRegistration.Enabled {
  189. // 'none' isn't shown in the REGCALLBACKS vars
  190. var enabledCallbacks []string
  191. for _, name := range server.accountRegistration.EnabledCallbacks {
  192. if name != "*" {
  193. enabledCallbacks = append(enabledCallbacks, name)
  194. }
  195. }
  196. isupport.Add("REGCOMMANDS", "CREATE,VERIFY")
  197. isupport.Add("REGCALLBACKS", strings.Join(enabledCallbacks, ","))
  198. isupport.Add("REGCREDTYPES", "passphrase,certfp")
  199. }
  200. server.configurableStateMutex.RUnlock()
  201. isupport.RegenerateCachedReply()
  202. server.configurableStateMutex.Lock()
  203. server.isupport = isupport
  204. server.configurableStateMutex.Unlock()
  205. }
  206. func loadChannelList(channel *Channel, list string, maskMode Mode) {
  207. if list == "" {
  208. return
  209. }
  210. channel.lists[maskMode].AddAll(strings.Split(list, " "))
  211. }
  212. // Shutdown shuts down the server.
  213. func (server *Server) Shutdown() {
  214. //TODO(dan): Make sure we disallow new nicks
  215. server.clients.ByNickMutex.RLock()
  216. for _, client := range server.clients.ByNick {
  217. client.Notice("Server is shutting down")
  218. }
  219. server.clients.ByNickMutex.RUnlock()
  220. if err := server.store.Close(); err != nil {
  221. server.logger.Error("shutdown", fmt.Sprintln("Could not close datastore:", err))
  222. }
  223. }
  224. // Run starts the server.
  225. func (server *Server) Run() {
  226. // defer closing db/store
  227. defer server.store.Close()
  228. done := false
  229. for !done {
  230. select {
  231. case <-server.signals:
  232. server.Shutdown()
  233. done = true
  234. case <-server.rehashSignal:
  235. server.logger.Info("rehash", "Rehashing due to SIGHUP")
  236. go func() {
  237. err := server.rehash()
  238. if err != nil {
  239. server.logger.Error("rehash", fmt.Sprintln("Failed to rehash:", err.Error()))
  240. }
  241. }()
  242. case conn := <-server.newConns:
  243. // check IP address
  244. ipaddr := net.ParseIP(IPString(conn.Conn.RemoteAddr()))
  245. if ipaddr == nil {
  246. conn.Conn.Write([]byte(couldNotParseIPMsg))
  247. conn.Conn.Close()
  248. continue
  249. }
  250. isBanned, banMsg := server.checkBans(ipaddr)
  251. if isBanned {
  252. // this might not show up properly on some clients, but our objective here is just to close the connection out before it has a load impact on us
  253. conn.Conn.Write([]byte(fmt.Sprintf(errorMsg, banMsg)))
  254. conn.Conn.Close()
  255. continue
  256. }
  257. server.logger.Debug("localconnect-ip", fmt.Sprintf("Client connecting from %v", ipaddr))
  258. // prolly don't need to alert snomasks on this, only on connection reg
  259. go NewClient(server, conn.Conn, conn.IsTLS)
  260. continue
  261. }
  262. }
  263. }
  264. func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) {
  265. // check DLINEs
  266. isBanned, info := server.dlines.CheckIP(ipaddr)
  267. if isBanned {
  268. return true, info.BanMessage("You are banned from this server (%s)")
  269. }
  270. // check connection limits
  271. server.connectionLimitsMutex.Lock()
  272. err := server.connectionLimits.AddClient(ipaddr, false)
  273. server.connectionLimitsMutex.Unlock()
  274. if err != nil {
  275. // too many connections from one client, tell the client and close the connection
  276. return true, "Too many clients from your network"
  277. }
  278. // check connection throttle
  279. server.connectionThrottleMutex.Lock()
  280. err = server.connectionThrottle.AddClient(ipaddr)
  281. server.connectionThrottleMutex.Unlock()
  282. if err != nil {
  283. // too many connections too quickly from client, tell them and close the connection
  284. length := &IPRestrictTime{
  285. Duration: server.connectionThrottle.BanDuration,
  286. Expires: time.Now().Add(server.connectionThrottle.BanDuration),
  287. }
  288. server.dlines.AddIP(ipaddr, length, server.connectionThrottle.BanMessage, "Exceeded automated connection throttle")
  289. // they're DLINE'd for 15 minutes or whatever, so we can reset the connection throttle now,
  290. // and once their temporary DLINE is finished they can fill up the throttler again
  291. server.connectionThrottle.ResetFor(ipaddr)
  292. // 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
  293. return true, server.connectionThrottle.BanMessage
  294. }
  295. return false, ""
  296. }
  297. //
  298. // IRC protocol listeners
  299. //
  300. // createListener starts the given listeners.
  301. func (server *Server) createListener(addr string, tlsConfig *tls.Config) *ListenerWrapper {
  302. // make listener
  303. listener, err := net.Listen("tcp", addr)
  304. if err != nil {
  305. log.Fatal(server, "listen error: ", err)
  306. }
  307. // throw our details to the server so we can be modified/killed later
  308. wrapper := ListenerWrapper{
  309. listener: listener,
  310. tlsConfig: tlsConfig,
  311. shouldStop: false,
  312. stopEvent: make(chan bool, 1),
  313. }
  314. var shouldStop bool
  315. // setup accept goroutine
  316. go func() {
  317. for {
  318. conn, err := listener.Accept()
  319. // synchronously access config data:
  320. // whether TLS is enabled and whether we should stop listening
  321. wrapper.configMutex.Lock()
  322. shouldStop = wrapper.shouldStop
  323. tlsConfig = wrapper.tlsConfig
  324. wrapper.configMutex.Unlock()
  325. if err == nil {
  326. if tlsConfig != nil {
  327. conn = tls.Server(conn, tlsConfig)
  328. }
  329. newConn := clientConn{
  330. Conn: conn,
  331. IsTLS: tlsConfig != nil,
  332. }
  333. // hand off the connection
  334. server.newConns <- newConn
  335. }
  336. if shouldStop {
  337. listener.Close()
  338. wrapper.stopEvent <- true
  339. return
  340. }
  341. }
  342. }()
  343. return &wrapper
  344. }
  345. // generateMessageID returns a network-unique message ID.
  346. func (server *Server) generateMessageID() string {
  347. return fmt.Sprintf("%s-%s", strconv.FormatInt(time.Now().UTC().UnixNano(), 10), strconv.FormatInt(rand.Int63(), 10))
  348. }
  349. //
  350. // server functionality
  351. //
  352. func (server *Server) tryRegister(c *Client) {
  353. if c.registered || !c.HasNick() || !c.HasUsername() ||
  354. (c.capState == CapNegotiating) {
  355. return
  356. }
  357. // check KLINEs
  358. isBanned, info := server.klines.CheckMasks(c.AllNickmasks()...)
  359. if isBanned {
  360. reason := info.Reason
  361. if info.Time != nil {
  362. reason += fmt.Sprintf(" [%s]", info.Time.Duration.String())
  363. }
  364. c.Send(nil, "", "ERROR", fmt.Sprintf("You are banned from this server (%s)", reason))
  365. c.quitMessageSent = true
  366. c.destroy()
  367. return
  368. }
  369. // continue registration
  370. server.logger.Debug("localconnect", fmt.Sprintf("Client registered [%s] [u:%s] [r:%s]", c.nick, c.username, c.realname))
  371. server.snomasks.Send(sno.LocalConnects, fmt.Sprintf(ircfmt.Unescape("Client registered $c[grey][$r%s$c[grey]] [u:$r%s$c[grey]] [h:$r%s$c[grey]] [r:$r%s$c[grey]]"), c.nick, c.username, c.rawHostname, c.realname))
  372. c.Register()
  373. // send welcome text
  374. //NOTE(dan): we specifically use the NICK here instead of the nickmask
  375. // see http://modern.ircdocs.horse/#rplwelcome-001 for details on why we avoid using the nickmask
  376. c.Send(nil, server.name, RPL_WELCOME, c.nick, fmt.Sprintf("Welcome to the Internet Relay Network %s", c.nick))
  377. c.Send(nil, server.name, RPL_YOURHOST, c.nick, fmt.Sprintf("Your host is %s, running version %s", server.name, Ver))
  378. c.Send(nil, server.name, RPL_CREATED, c.nick, fmt.Sprintf("This server was created %s", server.ctime.Format(time.RFC1123)))
  379. //TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
  380. c.Send(nil, server.name, RPL_MYINFO, c.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
  381. c.RplISupport()
  382. server.MOTD(c)
  383. c.Send(nil, c.nickMaskString, RPL_UMODEIS, c.nick, c.ModeString())
  384. if server.logger.DumpingRawInOut {
  385. c.Notice("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
  386. }
  387. }
  388. // MOTD serves the Message of the Day.
  389. func (server *Server) MOTD(client *Client) {
  390. server.configurableStateMutex.RLock()
  391. motdLines := server.motdLines
  392. server.configurableStateMutex.RUnlock()
  393. if len(motdLines) < 1 {
  394. client.Send(nil, server.name, ERR_NOMOTD, client.nick, "MOTD File is missing")
  395. return
  396. }
  397. client.Send(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf("- %s Message of the day - ", server.name))
  398. for _, line := range motdLines {
  399. client.Send(nil, server.name, RPL_MOTD, client.nick, line)
  400. }
  401. client.Send(nil, server.name, RPL_ENDOFMOTD, client.nick, "End of MOTD command")
  402. }
  403. //
  404. // registration commands
  405. //
  406. // PASS <password>
  407. func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  408. if client.registered {
  409. client.Send(nil, server.name, ERR_ALREADYREGISTRED, client.nick, "You may not reregister")
  410. return false
  411. }
  412. // if no password exists, skip checking
  413. if len(server.password) == 0 {
  414. client.authorized = true
  415. return false
  416. }
  417. // check the provided password
  418. password := []byte(msg.Params[0])
  419. if ComparePassword(server.password, password) != nil {
  420. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  421. client.Send(nil, server.name, "ERROR", "Password incorrect")
  422. return true
  423. }
  424. client.authorized = true
  425. return false
  426. }
  427. // USER <username> * 0 <realname>
  428. func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  429. if client.registered {
  430. client.Send(nil, server.name, ERR_ALREADYREGISTRED, client.nick, "You may not reregister")
  431. return false
  432. }
  433. if !client.authorized {
  434. client.Quit("Bad password")
  435. return true
  436. }
  437. if client.username != "" && client.realname != "" {
  438. return false
  439. }
  440. // confirm that username is valid
  441. //
  442. _, err := CasefoldName(msg.Params[0])
  443. if err != nil {
  444. client.Send(nil, "", "ERROR", "Malformed username")
  445. return true
  446. }
  447. if !client.HasUsername() {
  448. client.username = "~" + msg.Params[0]
  449. // don't bother updating nickmask here, it's not valid anyway
  450. }
  451. if client.realname == "" {
  452. client.realname = msg.Params[3]
  453. }
  454. server.tryRegister(client)
  455. return false
  456. }
  457. // QUIT [<reason>]
  458. func quitHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  459. reason := "Quit"
  460. if len(msg.Params) > 0 {
  461. reason += ": " + msg.Params[0]
  462. }
  463. client.Quit(reason)
  464. return true
  465. }
  466. //
  467. // normal commands
  468. //
  469. // PING <server1> [<server2>]
  470. func pingHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  471. client.Send(nil, server.name, "PONG", msg.Params...)
  472. return false
  473. }
  474. // PONG <server> [ <server2> ]
  475. func pongHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  476. // client gets touched when they send this command, so we don't need to do anything
  477. return false
  478. }
  479. // RENAME <oldchan> <newchan> [<reason>]
  480. //TODO(dan): Clean up this function so it doesn't look like an eldrich horror... prolly by putting it into a server.renameChannel function.
  481. func renameHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  482. // get lots of locks... make sure nobody touches anything while we're doing this
  483. server.registeredChannelsMutex.Lock()
  484. defer server.registeredChannelsMutex.Unlock()
  485. server.channels.ChansLock.Lock()
  486. defer server.channels.ChansLock.Unlock()
  487. oldName := strings.TrimSpace(msg.Params[0])
  488. newName := strings.TrimSpace(msg.Params[1])
  489. reason := "No reason"
  490. if 2 < len(msg.Params) {
  491. reason = msg.Params[2]
  492. }
  493. // check for all the reasons why the rename couldn't happen
  494. casefoldedOldName, err := CasefoldChannel(oldName)
  495. if err != nil {
  496. //TODO(dan): Change this to ERR_CANNOTRENAME
  497. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "RENAME", oldName, "Old channel name is invalid")
  498. return false
  499. }
  500. channel := server.channels.Chans[casefoldedOldName]
  501. if channel == nil {
  502. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, oldName, "No such channel")
  503. return false
  504. }
  505. //TODO(dan): allow IRCops to do this?
  506. if !channel.ClientIsAtLeast(client, Operator) {
  507. client.Send(nil, server.name, ERR_CHANOPRIVSNEEDED, client.nick, oldName, "Only chanops can rename channels")
  508. return false
  509. }
  510. channel.membersMutex.Lock()
  511. defer channel.membersMutex.Unlock()
  512. casefoldedNewName, err := CasefoldChannel(newName)
  513. if err != nil {
  514. //TODO(dan): Change this to ERR_CANNOTRENAME
  515. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "RENAME", newName, "New channel name is invalid")
  516. return false
  517. }
  518. newChannel := server.channels.Chans[casefoldedNewName]
  519. if newChannel != nil {
  520. //TODO(dan): Change this to ERR_CHANNAMEINUSE
  521. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "RENAME", newName, "New channel name is in use")
  522. return false
  523. }
  524. var canEdit bool
  525. server.store.Update(func(tx *buntdb.Tx) error {
  526. chanReg := server.loadChannelNoMutex(tx, casefoldedOldName)
  527. if chanReg == nil || !client.LoggedIntoAccount() || client.account.Name == chanReg.Founder {
  528. canEdit = true
  529. }
  530. chanReg = server.loadChannelNoMutex(tx, casefoldedNewName)
  531. if chanReg != nil {
  532. canEdit = false
  533. }
  534. return nil
  535. })
  536. if !canEdit {
  537. //TODO(dan): Change this to ERR_CANNOTRENAME
  538. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "RENAME", oldName, "Only channel founders can change registered channels")
  539. return false
  540. }
  541. // perform the channel rename
  542. server.channels.Chans[casefoldedOldName] = nil
  543. server.channels.Chans[casefoldedNewName] = channel
  544. channel.name = strings.TrimSpace(msg.Params[1])
  545. channel.nameCasefolded = casefoldedNewName
  546. // rename stored channel info if any exists
  547. server.store.Update(func(tx *buntdb.Tx) error {
  548. chanReg := server.loadChannelNoMutex(tx, casefoldedOldName)
  549. if chanReg == nil {
  550. return nil
  551. }
  552. server.deleteChannelNoMutex(tx, casefoldedOldName)
  553. chanReg.Name = newName
  554. server.saveChannelNoMutex(tx, casefoldedNewName, *chanReg)
  555. return nil
  556. })
  557. // send RENAME messages
  558. for mcl := range channel.members {
  559. if mcl.capabilities.Has(caps.Rename) {
  560. mcl.Send(nil, client.nickMaskString, "RENAME", oldName, newName, reason)
  561. } else {
  562. mcl.Send(nil, mcl.nickMaskString, "PART", oldName, fmt.Sprintf("Channel renamed: %s", reason))
  563. if mcl.capabilities.Has(caps.ExtendedJoin) {
  564. accountName := "*"
  565. if mcl.account != nil {
  566. accountName = mcl.account.Name
  567. }
  568. mcl.Send(nil, mcl.nickMaskString, "JOIN", newName, accountName, mcl.realname)
  569. } else {
  570. mcl.Send(nil, mcl.nickMaskString, "JOIN", newName)
  571. }
  572. }
  573. }
  574. return false
  575. }
  576. // JOIN <channel>{,<channel>} [<key>{,<key>}]
  577. func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  578. // kill JOIN 0 requests
  579. if msg.Params[0] == "0" {
  580. client.Notice("JOIN 0 is not allowed")
  581. return false
  582. }
  583. // handle regular JOINs
  584. channels := strings.Split(msg.Params[0], ",")
  585. var keys []string
  586. if len(msg.Params) > 1 {
  587. keys = strings.Split(msg.Params[1], ",")
  588. }
  589. // get lock
  590. server.channelJoinPartMutex.Lock()
  591. defer server.channelJoinPartMutex.Unlock()
  592. for i, name := range channels {
  593. casefoldedName, err := CasefoldChannel(name)
  594. if err != nil {
  595. if len(name) > 0 {
  596. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
  597. }
  598. continue
  599. }
  600. channel := server.channels.Get(casefoldedName)
  601. if channel == nil {
  602. if len(casefoldedName) > server.getLimits().ChannelLen {
  603. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
  604. continue
  605. }
  606. channel = NewChannel(server, name, true)
  607. }
  608. var key string
  609. if len(keys) > i {
  610. key = keys[i]
  611. }
  612. channel.Join(client, key)
  613. }
  614. return false
  615. }
  616. // PART <channel>{,<channel>} [<reason>]
  617. func partHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  618. channels := strings.Split(msg.Params[0], ",")
  619. 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
  620. if len(msg.Params) > 1 {
  621. reason = msg.Params[1]
  622. }
  623. // get lock
  624. server.channelJoinPartMutex.Lock()
  625. defer server.channelJoinPartMutex.Unlock()
  626. for _, chname := range channels {
  627. casefoldedChannelName, err := CasefoldChannel(chname)
  628. channel := server.channels.Get(casefoldedChannelName)
  629. if err != nil || channel == nil {
  630. if len(chname) > 0 {
  631. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  632. }
  633. continue
  634. }
  635. channel.Part(client, reason)
  636. }
  637. return false
  638. }
  639. // TOPIC <channel> [<topic>]
  640. func topicHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  641. name, err := CasefoldChannel(msg.Params[0])
  642. channel := server.channels.Get(name)
  643. if err != nil || channel == nil {
  644. if len(msg.Params[0]) > 0 {
  645. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, msg.Params[0], "No such channel")
  646. }
  647. return false
  648. }
  649. if len(msg.Params) > 1 {
  650. channel.SetTopic(client, msg.Params[1])
  651. } else {
  652. channel.GetTopic(client)
  653. }
  654. return false
  655. }
  656. // wordWrap wraps the given text into a series of lines that don't exceed lineWidth characters.
  657. func wordWrap(text string, lineWidth int) []string {
  658. var lines []string
  659. var cacheLine, cacheWord string
  660. for _, char := range text {
  661. if char == '\r' {
  662. continue
  663. } else if char == '\n' {
  664. cacheLine += cacheWord
  665. lines = append(lines, cacheLine)
  666. cacheWord = ""
  667. cacheLine = ""
  668. } else if (char == ' ' || char == '-') && len(cacheLine)+len(cacheWord)+1 < lineWidth {
  669. // natural word boundary
  670. cacheLine += cacheWord + string(char)
  671. cacheWord = ""
  672. } else if lineWidth <= len(cacheLine)+len(cacheWord)+1 {
  673. // time to wrap to next line
  674. if len(cacheLine) < (lineWidth / 2) {
  675. // this word takes up more than half a line... just split in the middle of the word
  676. cacheLine += cacheWord + string(char)
  677. cacheWord = ""
  678. } else {
  679. cacheWord += string(char)
  680. }
  681. lines = append(lines, cacheLine)
  682. cacheLine = ""
  683. } else {
  684. // normal character
  685. cacheWord += string(char)
  686. }
  687. }
  688. if 0 < len(cacheWord) {
  689. cacheLine += cacheWord
  690. }
  691. if 0 < len(cacheLine) {
  692. lines = append(lines, cacheLine)
  693. }
  694. return lines
  695. }
  696. // SplitMessage represents a message that's been split for sending.
  697. type SplitMessage struct {
  698. For512 []string
  699. ForMaxLine string
  700. }
  701. func (server *Server) splitMessage(original string, origIs512 bool) SplitMessage {
  702. var newSplit SplitMessage
  703. newSplit.ForMaxLine = original
  704. if !origIs512 {
  705. newSplit.For512 = wordWrap(original, 400)
  706. } else {
  707. newSplit.For512 = []string{original}
  708. }
  709. return newSplit
  710. }
  711. // PRIVMSG <target>{,<target>} <message>
  712. func privmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  713. clientOnlyTags := GetClientOnlyTags(msg.Tags)
  714. targets := strings.Split(msg.Params[0], ",")
  715. message := msg.Params[1]
  716. // split privmsg
  717. splitMsg := server.splitMessage(message, !client.capabilities.Has(caps.MaxLine))
  718. for i, targetString := range targets {
  719. // max of four targets per privmsg
  720. if i > maxTargets-1 {
  721. break
  722. }
  723. prefixes, targetString := SplitChannelMembershipPrefixes(targetString)
  724. lowestPrefix := GetLowestChannelModePrefix(prefixes)
  725. // eh, no need to notify them
  726. if len(targetString) < 1 {
  727. continue
  728. }
  729. target, err := CasefoldChannel(targetString)
  730. if err == nil {
  731. channel := server.channels.Get(target)
  732. if channel == nil {
  733. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
  734. continue
  735. }
  736. if !channel.CanSpeak(client) {
  737. client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
  738. continue
  739. }
  740. msgid := server.generateMessageID()
  741. channel.SplitPrivMsg(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
  742. } else {
  743. target, err = CasefoldName(targetString)
  744. if target == "chanserv" {
  745. server.chanservReceivePrivmsg(client, message)
  746. continue
  747. } else if target == "nickserv" {
  748. server.nickservReceivePrivmsg(client, message)
  749. continue
  750. }
  751. user := server.clients.Get(target)
  752. if err != nil || user == nil {
  753. if len(target) > 0 {
  754. client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, target, "No such nick")
  755. }
  756. continue
  757. }
  758. if !user.capabilities.Has(caps.MessageTags) {
  759. clientOnlyTags = nil
  760. }
  761. msgid := server.generateMessageID()
  762. // restrict messages appropriately when +R is set
  763. // intentionally make the sending user think the message went through fine
  764. if !user.flags[RegisteredOnly] || client.registered {
  765. user.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
  766. }
  767. if client.capabilities.Has(caps.EchoMessage) {
  768. client.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "PRIVMSG", user.nick, splitMsg)
  769. }
  770. if user.flags[Away] {
  771. //TODO(dan): possibly implement cooldown of away notifications to users
  772. client.Send(nil, server.name, RPL_AWAY, user.nick, user.awayMessage)
  773. }
  774. }
  775. }
  776. return false
  777. }
  778. // TAGMSG <target>{,<target>}
  779. func tagmsgHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  780. clientOnlyTags := GetClientOnlyTags(msg.Tags)
  781. // no client-only tags, so we can drop it
  782. if clientOnlyTags == nil {
  783. return false
  784. }
  785. targets := strings.Split(msg.Params[0], ",")
  786. for i, targetString := range targets {
  787. // max of four targets per privmsg
  788. if i > maxTargets-1 {
  789. break
  790. }
  791. prefixes, targetString := SplitChannelMembershipPrefixes(targetString)
  792. lowestPrefix := GetLowestChannelModePrefix(prefixes)
  793. // eh, no need to notify them
  794. if len(targetString) < 1 {
  795. continue
  796. }
  797. target, err := CasefoldChannel(targetString)
  798. if err == nil {
  799. channel := server.channels.Get(target)
  800. if channel == nil {
  801. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, "No such channel")
  802. continue
  803. }
  804. if !channel.CanSpeak(client) {
  805. client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, "Cannot send to channel")
  806. continue
  807. }
  808. msgid := server.generateMessageID()
  809. channel.TagMsg(msgid, lowestPrefix, clientOnlyTags, client)
  810. } else {
  811. target, err = CasefoldName(targetString)
  812. user := server.clients.Get(target)
  813. if err != nil || user == nil {
  814. if len(target) > 0 {
  815. client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, target, "No such nick")
  816. }
  817. continue
  818. }
  819. msgid := server.generateMessageID()
  820. // end user can't receive tagmsgs
  821. if !user.capabilities.Has(caps.MessageTags) {
  822. continue
  823. }
  824. user.SendFromClient(msgid, client, clientOnlyTags, "TAGMSG", user.nick)
  825. if client.capabilities.Has(caps.EchoMessage) {
  826. client.SendFromClient(msgid, client, clientOnlyTags, "TAGMSG", user.nick)
  827. }
  828. if user.flags[Away] {
  829. //TODO(dan): possibly implement cooldown of away notifications to users
  830. client.Send(nil, server.name, RPL_AWAY, user.nick, user.awayMessage)
  831. }
  832. }
  833. }
  834. return false
  835. }
  836. // WhoisChannelsNames returns the common channel names between two users.
  837. func (client *Client) WhoisChannelsNames(target *Client) []string {
  838. isMultiPrefix := target.capabilities.Has(caps.MultiPrefix)
  839. var chstrs []string
  840. index := 0
  841. for channel := range client.channels {
  842. channel.membersMutex.RLock()
  843. defer channel.membersMutex.RUnlock()
  844. // channel is secret and the target can't see it
  845. if !target.flags[Operator] && channel.flags[Secret] && !channel.members.Has(target) {
  846. continue
  847. }
  848. chstrs = append(chstrs, channel.members[client].Prefixes(isMultiPrefix)+channel.name)
  849. index++
  850. }
  851. return chstrs
  852. }
  853. // WHOIS [ <target> ] <mask> *( "," <mask> )
  854. func whoisHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  855. var masksString string
  856. //var target string
  857. if len(msg.Params) > 1 {
  858. //target = msg.Params[0]
  859. masksString = msg.Params[1]
  860. } else {
  861. masksString = msg.Params[0]
  862. }
  863. if len(strings.TrimSpace(masksString)) < 1 {
  864. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "No masks given")
  865. return false
  866. }
  867. if client.flags[Operator] {
  868. masks := strings.Split(masksString, ",")
  869. for _, mask := range masks {
  870. casefoldedMask, err := Casefold(mask)
  871. if err != nil {
  872. client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, mask, "No such nick")
  873. continue
  874. }
  875. matches := server.clients.FindAll(casefoldedMask)
  876. if len(matches) == 0 {
  877. client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, mask, "No such nick")
  878. continue
  879. }
  880. for mclient := range matches {
  881. client.getWhoisOf(mclient)
  882. }
  883. }
  884. } else {
  885. // only get the first request
  886. casefoldedMask, err := Casefold(strings.Split(masksString, ",")[0])
  887. mclient := server.clients.Get(casefoldedMask)
  888. if err != nil || mclient == nil {
  889. client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, masksString, "No such nick")
  890. // fall through, ENDOFWHOIS is always sent
  891. } else {
  892. client.getWhoisOf(mclient)
  893. }
  894. }
  895. client.Send(nil, server.name, RPL_ENDOFWHOIS, client.nick, masksString, "End of /WHOIS list")
  896. return false
  897. }
  898. func (client *Client) getWhoisOf(target *Client) {
  899. client.Send(nil, client.server.name, RPL_WHOISUSER, client.nick, target.nick, target.username, target.hostname, "*", target.realname)
  900. whoischannels := client.WhoisChannelsNames(target)
  901. if whoischannels != nil {
  902. client.Send(nil, client.server.name, RPL_WHOISCHANNELS, client.nick, target.nick, strings.Join(whoischannels, " "))
  903. }
  904. if target.class != nil {
  905. client.Send(nil, client.server.name, RPL_WHOISOPERATOR, client.nick, target.nick, target.whoisLine)
  906. }
  907. if client.flags[Operator] || client == target {
  908. client.Send(nil, client.server.name, RPL_WHOISACTUALLY, client.nick, target.nick, fmt.Sprintf("%s@%s", target.username, LookupHostname(target.IPString())), target.IPString(), "Actual user@host, Actual IP")
  909. }
  910. if target.flags[TLS] {
  911. client.Send(nil, client.server.name, RPL_WHOISSECURE, client.nick, target.nick, "is using a secure connection")
  912. }
  913. if target.certfp != "" && (client.flags[Operator] || client == target) {
  914. client.Send(nil, client.server.name, RPL_WHOISCERTFP, client.nick, target.nick, fmt.Sprintf("has client certificate fingerprint %s", target.certfp))
  915. }
  916. 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")
  917. }
  918. // RplWhoReplyNoMutex returns the WHO reply between one user and another channel/user.
  919. // <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
  920. // :<hopcount> <real name>
  921. func (target *Client) RplWhoReplyNoMutex(channel *Channel, client *Client) {
  922. channelName := "*"
  923. flags := ""
  924. if client.flags[Away] {
  925. flags = "G"
  926. } else {
  927. flags = "H"
  928. }
  929. if client.flags[Operator] {
  930. flags += "*"
  931. }
  932. if channel != nil {
  933. flags += channel.members[client].Prefixes(target.capabilities.Has(caps.MultiPrefix))
  934. channelName = channel.name
  935. }
  936. 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)
  937. }
  938. func whoChannel(client *Client, channel *Channel, friends ClientSet) {
  939. channel.membersMutex.RLock()
  940. defer channel.membersMutex.RUnlock()
  941. for member := range channel.members {
  942. if !client.flags[Invisible] || friends[client] {
  943. client.RplWhoReplyNoMutex(channel, member)
  944. }
  945. }
  946. }
  947. // WHO [ <mask> [ "o" ] ]
  948. func whoHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  949. friends := client.Friends()
  950. var mask string
  951. if len(msg.Params) > 0 {
  952. casefoldedMask, err := Casefold(msg.Params[0])
  953. if err != nil {
  954. client.Send(nil, server.name, ERR_UNKNOWNERROR, "WHO", "Mask isn't valid")
  955. return false
  956. }
  957. mask = casefoldedMask
  958. }
  959. //TODO(dan): is this used and would I put this param in the Modern doc?
  960. // if not, can we remove it?
  961. //var operatorOnly bool
  962. //if len(msg.Params) > 1 && msg.Params[1] == "o" {
  963. // operatorOnly = true
  964. //}
  965. if mask == "" {
  966. server.channels.ChansLock.RLock()
  967. for _, channel := range server.channels.Chans {
  968. whoChannel(client, channel, friends)
  969. }
  970. server.channels.ChansLock.RUnlock()
  971. } else if mask[0] == '#' {
  972. // TODO implement wildcard matching
  973. //TODO(dan): ^ only for opers
  974. channel := server.channels.Get(mask)
  975. if channel != nil {
  976. whoChannel(client, channel, friends)
  977. }
  978. } else {
  979. for mclient := range server.clients.FindAll(mask) {
  980. client.RplWhoReplyNoMutex(nil, mclient)
  981. }
  982. }
  983. client.Send(nil, server.name, RPL_ENDOFWHO, client.nick, mask, "End of WHO list")
  984. return false
  985. }
  986. // OPER <name> <password>
  987. func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  988. name, err := CasefoldName(msg.Params[0])
  989. if err != nil {
  990. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  991. return true
  992. }
  993. if client.flags[Operator] == true {
  994. client.Send(nil, server.name, ERR_UNKNOWNERROR, "OPER", "You're already opered-up!")
  995. return false
  996. }
  997. server.configurableStateMutex.RLock()
  998. oper := server.operators[name]
  999. server.configurableStateMutex.RUnlock()
  1000. password := []byte(msg.Params[1])
  1001. err = ComparePassword(oper.Pass, password)
  1002. if (oper.Pass == nil) || (err != nil) {
  1003. client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
  1004. return true
  1005. }
  1006. client.flags[Operator] = true
  1007. client.operName = name
  1008. client.class = oper.Class
  1009. client.whoisLine = oper.WhoisLine
  1010. // push new vhost if one is set
  1011. if len(oper.Vhost) > 0 {
  1012. for fClient := range client.Friends(caps.ChgHost) {
  1013. fClient.SendFromClient("", client, nil, "CHGHOST", client.username, oper.Vhost)
  1014. }
  1015. // CHGHOST requires prefix nickmask to have original hostname, so do that before updating nickmask
  1016. client.vhost = oper.Vhost
  1017. client.updateNickMask("")
  1018. }
  1019. // set new modes
  1020. var applied ModeChanges
  1021. if 0 < len(oper.Modes) {
  1022. modeChanges, unknownChanges := ParseUserModeChanges(strings.Split(oper.Modes, " ")...)
  1023. applied = client.applyUserModeChanges(true, modeChanges)
  1024. if 0 < len(unknownChanges) {
  1025. var runes string
  1026. for r := range unknownChanges {
  1027. runes += string(r)
  1028. }
  1029. client.Notice(fmt.Sprintf("Could not apply mode changes: +%s", runes))
  1030. }
  1031. }
  1032. client.Send(nil, server.name, RPL_YOUREOPER, client.nick, "You are now an IRC operator")
  1033. applied = append(applied, ModeChange{
  1034. mode: Operator,
  1035. op: Add,
  1036. })
  1037. client.Send(nil, server.name, "MODE", client.nick, applied.String())
  1038. server.snomasks.Send(sno.LocalOpers, fmt.Sprintf(ircfmt.Unescape("Client opered up $c[grey][$r%s$c[grey], $r%s$c[grey]]"), client.nickMaskString, client.operName))
  1039. return false
  1040. }
  1041. // rehash reloads the config and applies the changes from the config file.
  1042. func (server *Server) rehash() error {
  1043. server.logger.Debug("rehash", "Starting rehash")
  1044. // only let one REHASH go on at a time
  1045. server.rehashMutex.Lock()
  1046. defer server.rehashMutex.Unlock()
  1047. server.logger.Debug("rehash", "Got rehash lock")
  1048. config, err := LoadConfig(server.configFilename)
  1049. if err != nil {
  1050. return fmt.Errorf("Error loading config file config: %s", err.Error())
  1051. }
  1052. err = server.applyConfig(config, false)
  1053. if err != nil {
  1054. return fmt.Errorf("Error applying config changes: %s", err.Error())
  1055. }
  1056. return nil
  1057. }
  1058. func (server *Server) applyConfig(config *Config, initial bool) error {
  1059. if initial {
  1060. server.ctime = time.Now()
  1061. server.configFilename = config.Filename
  1062. } else {
  1063. // enforce configs that can't be changed after launch:
  1064. if server.limits.LineLen.Tags != config.Limits.LineLen.Tags || server.limits.LineLen.Rest != config.Limits.LineLen.Rest {
  1065. return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
  1066. } else if server.name != config.Server.Name {
  1067. return fmt.Errorf("Server name cannot be changed after launching the server, rehash aborted")
  1068. }
  1069. }
  1070. casefoldedName, err := Casefold(config.Server.Name)
  1071. if err != nil {
  1072. return fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error())
  1073. }
  1074. // confirm connectionLimits are fine
  1075. connectionLimits, err := NewConnectionLimits(config.Server.ConnectionLimits)
  1076. if err != nil {
  1077. return fmt.Errorf("Error rehashing config file connection-limits: %s", err.Error())
  1078. }
  1079. // confirm connectionThrottler is fine
  1080. connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
  1081. if err != nil {
  1082. return fmt.Errorf("Error rehashing config file connection-throttle: %s", err.Error())
  1083. }
  1084. // confirm operator stuff all exists and is fine
  1085. operclasses, err := config.OperatorClasses()
  1086. if err != nil {
  1087. return fmt.Errorf("Error rehashing config file operclasses: %s", err.Error())
  1088. }
  1089. opers, err := config.Operators(operclasses)
  1090. if err != nil {
  1091. return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
  1092. }
  1093. // TODO: support rehash of existing operator perms?
  1094. // sanity checks complete, start modifying server state
  1095. if initial {
  1096. server.name = config.Server.Name
  1097. server.nameCasefolded = casefoldedName
  1098. }
  1099. server.networkName = config.Network.Name
  1100. server.configurableStateMutex.Lock()
  1101. if config.Server.Password != "" {
  1102. server.password = config.Server.PasswordBytes()
  1103. } else {
  1104. server.password = nil
  1105. }
  1106. server.configurableStateMutex.Unlock()
  1107. // apply new PROXY command restrictions
  1108. server.proxyAllowedFrom = config.Server.ProxyAllowedFrom
  1109. // apply new connectionlimits
  1110. server.connectionLimitsMutex.Lock()
  1111. server.connectionLimits = connectionLimits
  1112. server.connectionThrottleMutex.Lock()
  1113. server.connectionThrottle = connectionThrottle
  1114. server.clients.ByNickMutex.RLock()
  1115. for _, client := range server.clients.ByNick {
  1116. ipaddr := client.IP()
  1117. if ipaddr != nil {
  1118. server.connectionLimits.AddClient(ipaddr, true)
  1119. }
  1120. }
  1121. server.clients.ByNickMutex.RUnlock()
  1122. server.connectionThrottleMutex.Unlock()
  1123. server.connectionLimitsMutex.Unlock()
  1124. // setup new and removed caps
  1125. addedCaps := caps.NewSet()
  1126. removedCaps := caps.NewSet()
  1127. updatedCaps := caps.NewSet()
  1128. // SASL
  1129. if config.Accounts.AuthenticationEnabled && !server.accountAuthenticationEnabled {
  1130. // enabling SASL
  1131. SupportedCapabilities.Enable(caps.SASL)
  1132. CapValues.Set(caps.SASL, "PLAIN,EXTERNAL")
  1133. addedCaps.Add(caps.SASL)
  1134. }
  1135. if !config.Accounts.AuthenticationEnabled && server.accountAuthenticationEnabled {
  1136. // disabling SASL
  1137. SupportedCapabilities.Disable(caps.SASL)
  1138. removedCaps.Add(caps.SASL)
  1139. }
  1140. server.accountAuthenticationEnabled = config.Accounts.AuthenticationEnabled
  1141. // STS
  1142. stsValue := config.Server.STS.Value()
  1143. var stsDisabled bool
  1144. stsCurrentCapValue, _ := CapValues.Get(caps.STS)
  1145. server.logger.Debug("rehash", "STS Vals", stsCurrentCapValue, stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled))
  1146. if config.Server.STS.Enabled && !server.stsEnabled {
  1147. // enabling STS
  1148. SupportedCapabilities.Enable(caps.STS)
  1149. addedCaps.Add(caps.STS)
  1150. CapValues.Set(caps.STS, stsValue)
  1151. } else if !config.Server.STS.Enabled && server.stsEnabled {
  1152. // disabling STS
  1153. SupportedCapabilities.Disable(caps.STS)
  1154. removedCaps.Add(caps.STS)
  1155. stsDisabled = true
  1156. } else if config.Server.STS.Enabled && server.stsEnabled && stsValue != stsCurrentCapValue {
  1157. // STS policy updated
  1158. CapValues.Set(caps.STS, stsValue)
  1159. updatedCaps.Add(caps.STS)
  1160. }
  1161. server.stsEnabled = config.Server.STS.Enabled
  1162. // burst new and removed caps
  1163. var capBurstClients ClientSet
  1164. added := make(map[caps.Version]string)
  1165. var removed string
  1166. // updated caps get DEL'd and then NEW'd
  1167. // so, we can just add updated ones to both removed and added lists here and they'll be correctly handled
  1168. server.logger.Debug("rehash", "Updated Caps", updatedCaps.String(caps.Cap301, CapValues), strconv.Itoa(updatedCaps.Count()))
  1169. for _, capab := range updatedCaps.List() {
  1170. addedCaps.Enable(capab)
  1171. removedCaps.Enable(capab)
  1172. }
  1173. if 0 < addedCaps.Count() || 0 < removedCaps.Count() {
  1174. capBurstClients = server.clients.AllWithCaps(caps.CapNotify)
  1175. added[caps.Cap301] = addedCaps.String(caps.Cap301, CapValues)
  1176. added[caps.Cap302] = addedCaps.String(caps.Cap302, CapValues)
  1177. // removed never has values, so we leave it as Cap301
  1178. removed = removedCaps.String(caps.Cap301, CapValues)
  1179. }
  1180. for sClient := range capBurstClients {
  1181. if stsDisabled {
  1182. // remove STS policy
  1183. //TODO(dan): this is an ugly hack. we can write this better.
  1184. stsPolicy := "sts=duration=0"
  1185. if 0 < addedCaps.Count() {
  1186. added[caps.Cap302] = added[caps.Cap302] + " " + stsPolicy
  1187. } else {
  1188. addedCaps.Enable(caps.STS)
  1189. added[caps.Cap302] = stsPolicy
  1190. }
  1191. }
  1192. // DEL caps and then send NEW ones so that updated caps get removed/added correctly
  1193. if 0 < removedCaps.Count() {
  1194. sClient.Send(nil, server.name, "CAP", sClient.nick, "DEL", removed)
  1195. }
  1196. if 0 < addedCaps.Count() {
  1197. sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
  1198. }
  1199. }
  1200. // set server options
  1201. server.configurableStateMutex.Lock()
  1202. lineLenConfig := LineLenLimits{
  1203. Tags: config.Limits.LineLen.Tags,
  1204. Rest: config.Limits.LineLen.Rest,
  1205. }
  1206. server.limits = Limits{
  1207. AwayLen: int(config.Limits.AwayLen),
  1208. ChannelLen: int(config.Limits.ChannelLen),
  1209. KickLen: int(config.Limits.KickLen),
  1210. MonitorEntries: int(config.Limits.MonitorEntries),
  1211. NickLen: int(config.Limits.NickLen),
  1212. TopicLen: int(config.Limits.TopicLen),
  1213. ChanListModes: int(config.Limits.ChanListModes),
  1214. LineLen: lineLenConfig,
  1215. }
  1216. server.operclasses = *operclasses
  1217. server.operators = opers
  1218. server.checkIdent = config.Server.CheckIdent
  1219. // registration
  1220. accountReg := NewAccountRegistration(config.Accounts.Registration)
  1221. server.accountRegistration = &accountReg
  1222. server.channelRegistrationEnabled = config.Channels.Registration.Enabled
  1223. server.defaultChannelModes = ParseDefaultChannelModes(config)
  1224. server.configurableStateMutex.Unlock()
  1225. // set new sendqueue size
  1226. if config.Server.MaxSendQBytes != server.MaxSendQBytes {
  1227. server.configurableStateMutex.Lock()
  1228. server.MaxSendQBytes = config.Server.MaxSendQBytes
  1229. server.configurableStateMutex.Unlock()
  1230. // update on all clients
  1231. server.clients.ByNickMutex.RLock()
  1232. for _, sClient := range server.clients.ByNick {
  1233. sClient.socket.MaxSendQBytes = config.Server.MaxSendQBytes
  1234. }
  1235. server.clients.ByNickMutex.RUnlock()
  1236. }
  1237. // set RPL_ISUPPORT
  1238. oldISupportList := server.isupport
  1239. server.setISupport()
  1240. if oldISupportList != nil {
  1241. newISupportReplies := oldISupportList.GetDifference(server.isupport)
  1242. // push new info to all of our clients
  1243. server.clients.ByNickMutex.RLock()
  1244. for _, sClient := range server.clients.ByNick {
  1245. for _, tokenline := range newISupportReplies {
  1246. // ugly trickery ahead
  1247. sClient.Send(nil, server.name, RPL_ISUPPORT, append([]string{sClient.nick}, tokenline...)...)
  1248. }
  1249. }
  1250. server.clients.ByNickMutex.RUnlock()
  1251. }
  1252. server.loadMOTD(config.Server.MOTD)
  1253. if initial {
  1254. if err := server.loadDatastore(config.Datastore.Path); err != nil {
  1255. return err
  1256. }
  1257. }
  1258. // we are now open for business
  1259. server.setupListeners(config)
  1260. server.setupRestAPI(config)
  1261. return nil
  1262. }
  1263. func (server *Server) loadMOTD(motdPath string) error {
  1264. server.logger.Debug("rehash", "Loading MOTD")
  1265. motdLines := make([]string, 0)
  1266. if motdPath != "" {
  1267. file, err := os.Open(motdPath)
  1268. if err == nil {
  1269. defer file.Close()
  1270. reader := bufio.NewReader(file)
  1271. for {
  1272. line, err := reader.ReadString('\n')
  1273. if err != nil {
  1274. break
  1275. }
  1276. line = strings.TrimRight(line, "\r\n")
  1277. // "- " is the required prefix for MOTD, we just add it here to make
  1278. // bursting it out to clients easier
  1279. line = fmt.Sprintf("- %s", line)
  1280. motdLines = append(motdLines, line)
  1281. }
  1282. } else {
  1283. return err
  1284. }
  1285. }
  1286. server.configurableStateMutex.Lock()
  1287. server.motdLines = motdLines
  1288. server.configurableStateMutex.Unlock()
  1289. return nil
  1290. }
  1291. func (server *Server) loadDatastore(datastorePath string) error {
  1292. // open the datastore and load server state for which it (rather than config)
  1293. // is the source of truth
  1294. server.logger.Debug("startup", "Opening datastore")
  1295. db, err := OpenDatabase(datastorePath)
  1296. if err == nil {
  1297. server.store = db
  1298. } else {
  1299. return fmt.Errorf("Failed to open datastore: %s", err.Error())
  1300. }
  1301. // load *lines (from the datastores)
  1302. server.logger.Debug("startup", "Loading D/Klines")
  1303. server.loadDLines()
  1304. server.loadKLines()
  1305. // load password manager
  1306. server.logger.Debug("startup", "Loading passwords")
  1307. err = server.store.View(func(tx *buntdb.Tx) error {
  1308. saltString, err := tx.Get(keySalt)
  1309. if err != nil {
  1310. return fmt.Errorf("Could not retrieve salt string: %s", err.Error())
  1311. }
  1312. salt, err := base64.StdEncoding.DecodeString(saltString)
  1313. if err != nil {
  1314. return err
  1315. }
  1316. pwm := NewPasswordManager(salt)
  1317. server.passwords = &pwm
  1318. return nil
  1319. })
  1320. if err != nil {
  1321. return fmt.Errorf("Could not load salt: %s", err.Error())
  1322. }
  1323. return nil
  1324. }
  1325. func (server *Server) setupListeners(config *Config) {
  1326. // update or destroy all existing listeners
  1327. tlsListeners := config.TLSListeners()
  1328. for addr := range server.listeners {
  1329. currentListener := server.listeners[addr]
  1330. var stillConfigured bool
  1331. for _, newaddr := range config.Server.Listen {
  1332. if newaddr == addr {
  1333. stillConfigured = true
  1334. break
  1335. }
  1336. }
  1337. // pass new config information to the listener, to be picked up after
  1338. // its next Accept(). this is like sending over a buffered channel of
  1339. // size 1, but where sending a second item overwrites the buffered item
  1340. // instead of blocking.
  1341. currentListener.configMutex.Lock()
  1342. currentListener.shouldStop = !stillConfigured
  1343. currentListener.tlsConfig = tlsListeners[addr]
  1344. currentListener.configMutex.Unlock()
  1345. if stillConfigured {
  1346. server.logger.Info("listeners",
  1347. fmt.Sprintf("now listening on %s, tls=%t.", addr, (currentListener.tlsConfig != nil)),
  1348. )
  1349. } else {
  1350. // tell the listener it should stop by interrupting its Accept() call:
  1351. currentListener.listener.Close()
  1352. // TODO(golang1.10) delete stopEvent once issue #21856 is released
  1353. <-currentListener.stopEvent
  1354. delete(server.listeners, addr)
  1355. server.logger.Info("listeners", fmt.Sprintf("stopped listening on %s.", addr))
  1356. }
  1357. }
  1358. // create new listeners that were not previously configured
  1359. for _, newaddr := range config.Server.Listen {
  1360. _, exists := server.listeners[newaddr]
  1361. if !exists {
  1362. // make new listener
  1363. server.listeners[newaddr] = server.createListener(newaddr, tlsListeners[newaddr])
  1364. }
  1365. }
  1366. if len(tlsListeners) == 0 {
  1367. server.logger.Warning("startup", "You are not exposing an SSL/TLS listening port. You should expose at least one port (typically 6697) to accept TLS connections")
  1368. }
  1369. var usesStandardTLSPort bool
  1370. for addr := range config.TLSListeners() {
  1371. if strings.Contains(addr, "6697") {
  1372. usesStandardTLSPort = true
  1373. break
  1374. }
  1375. }
  1376. if 0 < len(tlsListeners) && !usesStandardTLSPort {
  1377. server.logger.Warning("startup", "Port 6697 is the standard TLS port for IRC. You should (also) expose port 6697 as a TLS port to ensure clients can connect securely")
  1378. }
  1379. }
  1380. func (server *Server) setupRestAPI(config *Config) {
  1381. restAPIEnabled := config.Server.RestAPI.Enabled
  1382. restAPIStarted := server.restAPIServer != nil
  1383. restAPIListenAddrChanged := server.restAPI.Listen != config.Server.RestAPI.Listen
  1384. // stop an existing REST server if it's been disabled or the addr changed
  1385. if restAPIStarted && (!restAPIEnabled || restAPIListenAddrChanged) {
  1386. ctx, _ := context.WithTimeout(context.Background(), httpShutdownTimeout)
  1387. server.restAPIServer.Shutdown(ctx)
  1388. server.restAPIServer.Close()
  1389. server.logger.Info("rehash", "server", fmt.Sprintf("%s rest API stopped on %s.", server.name, server.restAPI.Listen))
  1390. server.restAPIServer = nil
  1391. }
  1392. // start a new one if it's enabled or the addr changed
  1393. if restAPIEnabled && (!restAPIStarted || restAPIListenAddrChanged) {
  1394. server.restAPIServer, _ = StartRestAPI(server, config.Server.RestAPI.Listen)
  1395. server.logger.Info(
  1396. "rehash", "server",
  1397. fmt.Sprintf("%s rest API started on %s.", server.name, config.Server.RestAPI.Listen))
  1398. }
  1399. // save the config information
  1400. server.restAPI = config.Server.RestAPI
  1401. }
  1402. func (server *Server) GetDefaultChannelModes() Modes {
  1403. server.configurableStateMutex.RLock()
  1404. defer server.configurableStateMutex.RUnlock()
  1405. return server.defaultChannelModes
  1406. }
  1407. // REHASH
  1408. func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1409. server.logger.Info("rehash", fmt.Sprintf("REHASH command used by %s", client.nick))
  1410. err := server.rehash()
  1411. if err == nil {
  1412. client.Send(nil, server.name, RPL_REHASHING, client.nick, "ircd.yaml", "Rehashing")
  1413. } else {
  1414. server.logger.Error("rehash", fmt.Sprintln("Failed to rehash:", err.Error()))
  1415. client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "REHASH", err.Error())
  1416. }
  1417. return false
  1418. }
  1419. // AWAY [<message>]
  1420. func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1421. var isAway bool
  1422. var text string
  1423. if len(msg.Params) > 0 {
  1424. isAway = true
  1425. text = msg.Params[0]
  1426. awayLen := server.getLimits().AwayLen
  1427. if len(text) > awayLen {
  1428. text = text[:awayLen]
  1429. }
  1430. }
  1431. if isAway {
  1432. client.flags[Away] = true
  1433. } else {
  1434. delete(client.flags, Away)
  1435. }
  1436. client.awayMessage = text
  1437. var op ModeOp
  1438. if client.flags[Away] {
  1439. op = Add
  1440. client.Send(nil, server.name, RPL_NOWAWAY, client.nick, "You have been marked as being away")
  1441. } else {
  1442. op = Remove
  1443. client.Send(nil, server.name, RPL_UNAWAY, client.nick, "You are no longer marked as being away")
  1444. }
  1445. //TODO(dan): Should this be sent automagically as part of setting the flag/mode?
  1446. modech := ModeChanges{ModeChange{
  1447. mode: Away,
  1448. op: op,
  1449. }}
  1450. client.Send(nil, server.name, "MODE", client.nick, modech.String())
  1451. // dispatch away-notify
  1452. for friend := range client.Friends(caps.AwayNotify) {
  1453. if client.flags[Away] {
  1454. friend.SendFromClient("", client, nil, "AWAY", client.awayMessage)
  1455. } else {
  1456. friend.SendFromClient("", client, nil, "AWAY")
  1457. }
  1458. }
  1459. return false
  1460. }
  1461. // ISON <nick>{ <nick>}
  1462. func isonHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1463. var nicks = msg.Params
  1464. var err error
  1465. var casefoldedNick string
  1466. ison := make([]string, 0)
  1467. for _, nick := range nicks {
  1468. casefoldedNick, err = CasefoldName(nick)
  1469. if err != nil {
  1470. continue
  1471. }
  1472. if iclient := server.clients.Get(casefoldedNick); iclient != nil {
  1473. ison = append(ison, iclient.nick)
  1474. }
  1475. }
  1476. client.Send(nil, server.name, RPL_ISON, client.nick, strings.Join(nicks, " "))
  1477. return false
  1478. }
  1479. // MOTD [<target>]
  1480. func motdHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1481. //TODO(dan): hook this up when we have multiple servers I guess???
  1482. //var target string
  1483. //if len(msg.Params) > 0 {
  1484. // target = msg.Params[0]
  1485. //}
  1486. server.MOTD(client)
  1487. return false
  1488. }
  1489. // NOTICE <target>{,<target>} <message>
  1490. func noticeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1491. clientOnlyTags := GetClientOnlyTags(msg.Tags)
  1492. targets := strings.Split(msg.Params[0], ",")
  1493. message := msg.Params[1]
  1494. // split privmsg
  1495. splitMsg := server.splitMessage(message, !client.capabilities.Has(caps.MaxLine))
  1496. for i, targetString := range targets {
  1497. // max of four targets per privmsg
  1498. if i > maxTargets-1 {
  1499. break
  1500. }
  1501. prefixes, targetString := SplitChannelMembershipPrefixes(targetString)
  1502. lowestPrefix := GetLowestChannelModePrefix(prefixes)
  1503. target, cerr := CasefoldChannel(targetString)
  1504. if cerr == nil {
  1505. channel := server.channels.Get(target)
  1506. if channel == nil {
  1507. // errors silently ignored with NOTICE as per RFC
  1508. continue
  1509. }
  1510. if !channel.CanSpeak(client) {
  1511. // errors silently ignored with NOTICE as per RFC
  1512. continue
  1513. }
  1514. msgid := server.generateMessageID()
  1515. channel.SplitNotice(msgid, lowestPrefix, clientOnlyTags, client, splitMsg)
  1516. } else {
  1517. target, err := CasefoldName(targetString)
  1518. if err != nil {
  1519. continue
  1520. }
  1521. if target == "chanserv" {
  1522. server.chanservReceiveNotice(client, message)
  1523. continue
  1524. } else if target == "nickserv" {
  1525. server.nickservReceiveNotice(client, message)
  1526. continue
  1527. }
  1528. user := server.clients.Get(target)
  1529. if user == nil {
  1530. // errors silently ignored with NOTICE as per RFC
  1531. continue
  1532. }
  1533. if !user.capabilities.Has(caps.MessageTags) {
  1534. clientOnlyTags = nil
  1535. }
  1536. msgid := server.generateMessageID()
  1537. // restrict messages appropriately when +R is set
  1538. // intentionally make the sending user think the message went through fine
  1539. if !user.flags[RegisteredOnly] || client.registered {
  1540. user.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
  1541. }
  1542. if client.capabilities.Has(caps.EchoMessage) {
  1543. client.SendSplitMsgFromClient(msgid, client, clientOnlyTags, "NOTICE", user.nick, splitMsg)
  1544. }
  1545. }
  1546. }
  1547. return false
  1548. }
  1549. // KICK <channel>{,<channel>} <user>{,<user>} [<comment>]
  1550. func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1551. channels := strings.Split(msg.Params[0], ",")
  1552. users := strings.Split(msg.Params[1], ",")
  1553. if (len(channels) != len(users)) && (len(users) != 1) {
  1554. client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, "KICK", "Not enough parameters")
  1555. return false
  1556. }
  1557. var kicks [][]string
  1558. for index, channel := range channels {
  1559. if len(users) == 1 {
  1560. kicks = append(kicks, []string{channel, users[0]})
  1561. } else {
  1562. kicks = append(kicks, []string{channel, users[index]})
  1563. }
  1564. }
  1565. var comment string
  1566. if len(msg.Params) > 2 {
  1567. comment = msg.Params[2]
  1568. }
  1569. for _, info := range kicks {
  1570. chname := info[0]
  1571. nickname := info[1]
  1572. casefoldedChname, err := CasefoldChannel(chname)
  1573. channel := server.channels.Get(casefoldedChname)
  1574. if err != nil || channel == nil {
  1575. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1576. continue
  1577. }
  1578. casefoldedNickname, err := CasefoldName(nickname)
  1579. target := server.clients.Get(casefoldedNickname)
  1580. if err != nil || target == nil {
  1581. client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, nickname, "No such nick")
  1582. continue
  1583. }
  1584. // make sure client has privs to kick the given user
  1585. //TODO(dan): split this into a separate function that checks if users have privs
  1586. // over other users, useful for things like -aoh as well
  1587. channel.membersMutex.Lock()
  1588. var hasPrivs bool
  1589. for _, mode := range ChannelPrivModes {
  1590. if channel.members[client][mode] {
  1591. hasPrivs = true
  1592. // admins cannot kick other admins
  1593. if mode == ChannelAdmin && channel.members[target][ChannelAdmin] {
  1594. hasPrivs = false
  1595. }
  1596. break
  1597. } else if channel.members[target][mode] {
  1598. break
  1599. }
  1600. }
  1601. if hasPrivs {
  1602. if comment == "" {
  1603. comment = nickname
  1604. }
  1605. channel.kickNoMutex(client, target, comment)
  1606. } else {
  1607. client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, chname, "You're not a channel operator")
  1608. }
  1609. channel.membersMutex.Unlock()
  1610. }
  1611. return false
  1612. }
  1613. // elistMatcher takes and matches ELIST conditions
  1614. type elistMatcher struct {
  1615. MinClientsActive bool
  1616. MinClients int
  1617. MaxClientsActive bool
  1618. MaxClients int
  1619. }
  1620. // Matches checks whether the given channel matches our matches.
  1621. func (matcher *elistMatcher) Matches(channel *Channel) bool {
  1622. channel.membersMutex.RLock()
  1623. defer channel.membersMutex.RUnlock()
  1624. if matcher.MinClientsActive {
  1625. if len(channel.members) < matcher.MinClients {
  1626. return false
  1627. }
  1628. }
  1629. if matcher.MaxClientsActive {
  1630. if matcher.MaxClients < len(channel.members) {
  1631. return false
  1632. }
  1633. }
  1634. return true
  1635. }
  1636. // LIST [<channel>{,<channel>}] [<elistcond>{,<elistcond>}]
  1637. func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1638. // get channels
  1639. var channels []string
  1640. for _, param := range msg.Params {
  1641. if 0 < len(param) && param[0] == '#' {
  1642. for _, channame := range strings.Split(param, ",") {
  1643. if 0 < len(channame) && channame[0] == '#' {
  1644. channels = append(channels, channame)
  1645. }
  1646. }
  1647. }
  1648. }
  1649. // get elist conditions
  1650. var matcher elistMatcher
  1651. for _, param := range msg.Params {
  1652. if len(param) < 1 {
  1653. continue
  1654. }
  1655. if param[0] == '<' {
  1656. param = param[1:]
  1657. val, err := strconv.Atoi(param)
  1658. if err != nil {
  1659. continue
  1660. }
  1661. matcher.MaxClientsActive = true
  1662. matcher.MaxClients = val - 1 // -1 because < means less than the given number
  1663. }
  1664. if param[0] == '>' {
  1665. param = param[1:]
  1666. val, err := strconv.Atoi(param)
  1667. if err != nil {
  1668. continue
  1669. }
  1670. matcher.MinClientsActive = true
  1671. matcher.MinClients = val + 1 // +1 because > means more than the given number
  1672. }
  1673. }
  1674. if len(channels) == 0 {
  1675. server.channels.ChansLock.RLock()
  1676. for _, channel := range server.channels.Chans {
  1677. if !client.flags[Operator] && channel.flags[Secret] {
  1678. continue
  1679. }
  1680. if matcher.Matches(channel) {
  1681. client.RplList(channel)
  1682. }
  1683. }
  1684. server.channels.ChansLock.RUnlock()
  1685. } else {
  1686. // limit regular users to only listing one channel
  1687. if !client.flags[Operator] {
  1688. channels = channels[:1]
  1689. }
  1690. for _, chname := range channels {
  1691. casefoldedChname, err := CasefoldChannel(chname)
  1692. channel := server.channels.Get(casefoldedChname)
  1693. if err != nil || channel == nil || (!client.flags[Operator] && channel.flags[Secret]) {
  1694. if len(chname) > 0 {
  1695. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1696. }
  1697. continue
  1698. }
  1699. if matcher.Matches(channel) {
  1700. client.RplList(channel)
  1701. }
  1702. }
  1703. }
  1704. client.Send(nil, server.name, RPL_LISTEND, client.nick, "End of LIST")
  1705. return false
  1706. }
  1707. // RplList returns the RPL_LIST numeric for the given channel.
  1708. func (target *Client) RplList(channel *Channel) {
  1709. channel.membersMutex.RLock()
  1710. defer channel.membersMutex.RUnlock()
  1711. // get the correct number of channel members
  1712. var memberCount int
  1713. if target.flags[Operator] || channel.members.Has(target) {
  1714. memberCount = len(channel.members)
  1715. } else {
  1716. for member := range channel.members {
  1717. if !member.flags[Invisible] {
  1718. memberCount++
  1719. }
  1720. }
  1721. }
  1722. target.Send(nil, target.server.name, RPL_LIST, target.nick, channel.name, strconv.Itoa(memberCount), channel.topic)
  1723. }
  1724. // NAMES [<channel>{,<channel>}]
  1725. func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1726. var channels []string
  1727. if len(msg.Params) > 0 {
  1728. channels = strings.Split(msg.Params[0], ",")
  1729. }
  1730. //var target string
  1731. //if len(msg.Params) > 1 {
  1732. // target = msg.Params[1]
  1733. //}
  1734. if len(channels) == 0 {
  1735. server.channels.ChansLock.RLock()
  1736. for _, channel := range server.channels.Chans {
  1737. channel.Names(client)
  1738. }
  1739. server.channels.ChansLock.RUnlock()
  1740. return false
  1741. }
  1742. // limit regular users to only listing one channel
  1743. if !client.flags[Operator] {
  1744. channels = channels[:1]
  1745. }
  1746. for _, chname := range channels {
  1747. casefoldedChname, err := CasefoldChannel(chname)
  1748. channel := server.channels.Get(casefoldedChname)
  1749. if err != nil || channel == nil {
  1750. if len(chname) > 0 {
  1751. client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, "No such channel")
  1752. }
  1753. continue
  1754. }
  1755. channel.Names(client)
  1756. }
  1757. return false
  1758. }
  1759. // VERSION [<server>]
  1760. func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1761. var target string
  1762. if len(msg.Params) > 0 {
  1763. target = msg.Params[0]
  1764. }
  1765. casefoldedTarget, err := Casefold(target)
  1766. if target != "" && (err != nil || casefoldedTarget != server.nameCasefolded) {
  1767. client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
  1768. return false
  1769. }
  1770. client.Send(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
  1771. client.RplISupport()
  1772. return false
  1773. }
  1774. // INVITE <nickname> <channel>
  1775. func inviteHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1776. nickname := msg.Params[0]
  1777. channelName := msg.Params[1]
  1778. casefoldedNickname, err := CasefoldName(nickname)
  1779. target := server.clients.Get(casefoldedNickname)
  1780. if err != nil || target == nil {
  1781. client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, nickname, "No such nick")
  1782. return false
  1783. }
  1784. casefoldedChannelName, err := CasefoldChannel(channelName)
  1785. channel := server.channels.Get(casefoldedChannelName)
  1786. if err != nil || channel == nil {
  1787. client.Send(nil, server.name, RPL_INVITING, client.nick, target.nick, channelName)
  1788. target.Send(nil, client.nickMaskString, "INVITE", target.nick, channel.name)
  1789. return true
  1790. }
  1791. channel.Invite(target, client)
  1792. return false
  1793. }
  1794. // TIME [<server>]
  1795. func timeHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1796. var target string
  1797. if len(msg.Params) > 0 {
  1798. target = msg.Params[0]
  1799. }
  1800. casefoldedTarget, err := Casefold(target)
  1801. if (target != "") && err != nil || (casefoldedTarget != server.nameCasefolded) {
  1802. client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
  1803. return false
  1804. }
  1805. client.Send(nil, server.name, RPL_TIME, client.nick, server.name, time.Now().Format(time.RFC1123))
  1806. return false
  1807. }
  1808. // KILL <nickname> <comment>
  1809. func killHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1810. nickname := msg.Params[0]
  1811. comment := "<no reason supplied>"
  1812. if len(msg.Params) > 1 {
  1813. comment = msg.Params[1]
  1814. }
  1815. casefoldedNickname, err := CasefoldName(nickname)
  1816. target := server.clients.Get(casefoldedNickname)
  1817. if err != nil || target == nil {
  1818. client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, nickname, "No such nick")
  1819. return false
  1820. }
  1821. quitMsg := fmt.Sprintf("Killed (%s (%s))", client.nick, comment)
  1822. server.snomasks.Send(sno.LocalKills, fmt.Sprintf(ircfmt.Unescape("%s$r was killed by %s $c[grey][$r%s$c[grey]]"), target.nick, client.nick, comment))
  1823. target.exitedSnomaskSent = true
  1824. target.Quit(quitMsg)
  1825. target.destroy()
  1826. return false
  1827. }
  1828. // WHOWAS <nickname> [<count> [<server>]]
  1829. func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1830. nicknames := strings.Split(msg.Params[0], ",")
  1831. var count int64
  1832. if len(msg.Params) > 1 {
  1833. count, _ = strconv.ParseInt(msg.Params[1], 10, 64)
  1834. }
  1835. //var target string
  1836. //if len(msg.Params) > 2 {
  1837. // target = msg.Params[2]
  1838. //}
  1839. for _, nickname := range nicknames {
  1840. results := server.whoWas.Find(nickname, count)
  1841. if len(results) == 0 {
  1842. if len(nickname) > 0 {
  1843. client.Send(nil, server.name, ERR_WASNOSUCHNICK, client.nick, nickname, "There was no such nickname")
  1844. }
  1845. } else {
  1846. for _, whoWas := range results {
  1847. client.Send(nil, server.name, RPL_WHOWASUSER, client.nick, whoWas.nickname, whoWas.username, whoWas.hostname, "*", whoWas.realname)
  1848. }
  1849. }
  1850. if len(nickname) > 0 {
  1851. client.Send(nil, server.name, RPL_ENDOFWHOWAS, client.nick, nickname, "End of WHOWAS")
  1852. }
  1853. }
  1854. return false
  1855. }
  1856. // LUSERS [<mask> [<server>]]
  1857. func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1858. //TODO(vegax87) Fix network statistics and additional parameters
  1859. var totalcount, invisiblecount, opercount int
  1860. server.clients.ByNickMutex.RLock()
  1861. defer server.clients.ByNickMutex.RUnlock()
  1862. for _, onlineusers := range server.clients.ByNick {
  1863. totalcount++
  1864. if onlineusers.flags[Invisible] {
  1865. invisiblecount++
  1866. }
  1867. if onlineusers.flags[Operator] {
  1868. opercount++
  1869. }
  1870. }
  1871. client.Send(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf("There are %d users and %d invisible on %d server(s)", totalcount, invisiblecount, 1))
  1872. client.Send(nil, server.name, RPL_LUSEROP, client.nick, fmt.Sprintf("%d IRC Operators online", opercount))
  1873. client.Send(nil, server.name, RPL_LUSERCHANNELS, client.nick, fmt.Sprintf("%d channels formed", server.channels.Len()))
  1874. client.Send(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf("I have %d clients and %d servers", totalcount, 1))
  1875. return false
  1876. }
  1877. // USERHOST <nickname> [<nickname> <nickname> ...]
  1878. func userhostHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1879. returnedNicks := make(map[string]bool)
  1880. for i, nickname := range msg.Params {
  1881. if i >= 10 {
  1882. break
  1883. }
  1884. casefoldedNickname, err := CasefoldName(nickname)
  1885. target := server.clients.Get(casefoldedNickname)
  1886. if err != nil || target == nil {
  1887. client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, nickname, "No such nick")
  1888. return false
  1889. }
  1890. if returnedNicks[casefoldedNickname] {
  1891. continue
  1892. }
  1893. // to prevent returning multiple results for a single nick
  1894. returnedNicks[casefoldedNickname] = true
  1895. var isOper, isAway string
  1896. if target.flags[Operator] {
  1897. isOper = "*"
  1898. }
  1899. if target.flags[Away] {
  1900. isAway = "-"
  1901. } else {
  1902. isAway = "+"
  1903. }
  1904. client.Send(nil, client.server.name, RPL_USERHOST, client.nick, fmt.Sprintf("%s%s=%s%s@%s", target.nick, isOper, isAway, target.username, target.hostname))
  1905. }
  1906. return false
  1907. }
  1908. // PROXY TCP4/6 SOURCEIP DESTIP SOURCEPORT DESTPORT
  1909. // http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt
  1910. func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  1911. // only allow unregistered clients to use this command
  1912. if client.registered {
  1913. return false
  1914. }
  1915. clientAddress := IPString(client.socket.conn.RemoteAddr())
  1916. clientHostname := client.hostname
  1917. for _, address := range server.proxyAllowedFrom {
  1918. if clientHostname == address || clientAddress == address {
  1919. proxiedIP := msg.Params[1]
  1920. // ensure IP is sane
  1921. parsedProxiedIP := net.ParseIP(proxiedIP)
  1922. if parsedProxiedIP == nil {
  1923. client.Quit(fmt.Sprintf("Proxied IP address is not valid: [%s]", proxiedIP))
  1924. return true
  1925. }
  1926. isBanned, banMsg := server.checkBans(parsedProxiedIP)
  1927. if isBanned {
  1928. client.Quit(banMsg)
  1929. return true
  1930. }
  1931. // override the client's regular IP
  1932. client.proxiedIP = msg.Params[1]
  1933. client.rawHostname = LookupHostname(msg.Params[1])
  1934. client.hostname = client.rawHostname
  1935. return false
  1936. }
  1937. }
  1938. client.Quit("PROXY command is not usable from your address")
  1939. return true
  1940. }