|
@@ -529,6 +529,7 @@ func brbHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
529
|
529
|
|
530
|
530
|
// CAP <subcmd> [<caps>]
|
531
|
531
|
func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
|
532
|
+ details := client.Details()
|
532
|
533
|
subCommand := strings.ToUpper(msg.Params[0])
|
533
|
534
|
toAdd := caps.NewSet()
|
534
|
535
|
toRemove := caps.NewSet()
|
|
@@ -571,10 +572,10 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
571
|
572
|
// the server.name source... otherwise it doesn't respond to the CAP message with
|
572
|
573
|
// anything and just hangs on connection.
|
573
|
574
|
//TODO(dan): limit number of caps and send it multiline in 3.2 style as appropriate.
|
574
|
|
- rb.Add(nil, server.name, "CAP", client.nick, subCommand, SupportedCapabilities.String(rb.session.capVersion, CapValues))
|
|
575
|
+ rb.Add(nil, server.name, "CAP", details.nick, subCommand, SupportedCapabilities.String(rb.session.capVersion, CapValues))
|
575
|
576
|
|
576
|
577
|
case "LIST":
|
577
|
|
- rb.Add(nil, server.name, "CAP", client.nick, subCommand, rb.session.capabilities.String(caps.Cap301, CapValues)) // values not sent on LIST so force 3.1
|
|
578
|
+ rb.Add(nil, server.name, "CAP", details.nick, subCommand, rb.session.capabilities.String(caps.Cap301, CapValues)) // values not sent on LIST so force 3.1
|
578
|
579
|
|
579
|
580
|
case "REQ":
|
580
|
581
|
if !client.registered {
|
|
@@ -582,13 +583,20 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
582
|
583
|
}
|
583
|
584
|
|
584
|
585
|
// make sure all capabilities actually exist
|
585
|
|
- if badCaps {
|
586
|
|
- rb.Add(nil, server.name, "CAP", client.nick, "NAK", capString)
|
|
586
|
+ // #511, #521: oragono.io/nope is a fake cap to trap bad clients who blindly request
|
|
587
|
+ // every offered capability. during registration, requesting it produces a quit,
|
|
588
|
+ // otherwise just a CAP NAK
|
|
589
|
+ if badCaps || (toAdd.Has(caps.Nope) && client.registered) {
|
|
590
|
+ rb.Add(nil, server.name, "CAP", details.nick, "NAK", capString)
|
587
|
591
|
return false
|
|
592
|
+ } else if toAdd.Has(caps.Nope) && !client.registered {
|
|
593
|
+ client.Quit(client.t("Requesting the oragono.io/nope CAP is forbidden"), rb.session)
|
|
594
|
+ return true
|
588
|
595
|
}
|
|
596
|
+
|
589
|
597
|
rb.session.capabilities.Union(toAdd)
|
590
|
598
|
rb.session.capabilities.Subtract(toRemove)
|
591
|
|
- rb.Add(nil, server.name, "CAP", client.nick, "ACK", capString)
|
|
599
|
+ rb.Add(nil, server.name, "CAP", details.nick, "ACK", capString)
|
592
|
600
|
|
593
|
601
|
// if this is the first time the client is requesting a resume token,
|
594
|
602
|
// send it to them
|
|
@@ -600,13 +608,6 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
600
|
608
|
}
|
601
|
609
|
}
|
602
|
610
|
|
603
|
|
- // #511: oragono.io/nope is a fake cap to trap bad clients who blindly request
|
604
|
|
- // every offered capability:
|
605
|
|
- if toAdd.Has(caps.Nope) {
|
606
|
|
- client.Quit(client.t("Requesting the oragono.io/nope CAP is forbidden"), rb.session)
|
607
|
|
- return true
|
608
|
|
- }
|
609
|
|
-
|
610
|
611
|
// update maxlenrest, just in case they altered the maxline cap
|
611
|
612
|
rb.session.SetMaxlenRest()
|
612
|
613
|
|
|
@@ -616,7 +617,7 @@ func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Respo
|
616
|
617
|
}
|
617
|
618
|
|
618
|
619
|
default:
|
619
|
|
- rb.Add(nil, server.name, ERR_INVALIDCAPCMD, client.nick, subCommand, client.t("Invalid CAP subcommand"))
|
|
620
|
+ rb.Add(nil, server.name, ERR_INVALIDCAPCMD, details.nick, subCommand, client.t("Invalid CAP subcommand"))
|
620
|
621
|
}
|
621
|
622
|
return false
|
622
|
623
|
}
|