diff --git a/irc/chanserv.go b/irc/chanserv.go index f63cfe21..361f394a 100644 --- a/irc/chanserv.go +++ b/irc/chanserv.go @@ -952,7 +952,7 @@ func csHowToBanHandler(service *ircService, server *Server, client *Client, comm success = true if len(collateralDamage) != 0 { service.Notice(rb, fmt.Sprintf(client.t("Warning: this ban will affect %d other users:"), len(collateralDamage))) - for _, line := range utils.BuildTokenLines(400, collateralDamage, " ") { + for _, line := range utils.BuildTokenLines(maxLastArgLength, collateralDamage, " ") { service.Notice(rb, line) } } diff --git a/irc/handlers.go b/irc/handlers.go index 6374ad3c..b15e011a 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -199,13 +199,17 @@ func authenticateHandler(server *Server, client *Client, msg ircmsg.Message, rb // continue existing sasl session rawData := msg.Params[0] - if len(rawData) > 400 { + // https://ircv3.net/specs/extensions/sasl-3.1: + // "The response is encoded in Base64 (RFC 4648), then split to 400-byte chunks, + // and each chunk is sent as a separate AUTHENTICATE command." + saslMaxArgLength := 400 + if len(rawData) > saslMaxArgLength { rb.Add(nil, server.name, ERR_SASLTOOLONG, details.nick, client.t("SASL message too long")) session.sasl.Clear() return false - } else if len(rawData) == 400 { + } else if len(rawData) == saslMaxArgLength { // allow 4 'continuation' lines before rejecting for length - if len(session.sasl.value) >= 400*4 { + if len(session.sasl.value) >= saslMaxArgLength*4 { rb.Add(nil, server.name, ERR_SASLFAIL, details.nick, client.t("SASL authentication failed: Passphrase too long")) session.sasl.Clear() return false @@ -1062,7 +1066,7 @@ func extjwtHandler(server *Server, client *Client, msg ircmsg.Message, rb *Respo tokenString, err := sConfig.Sign(claims) if err == nil { - maxTokenLength := 400 + maxTokenLength := maxLastArgLength for maxTokenLength < len(tokenString) { rb.Add(nil, server.name, "EXTJWT", msg.Params[0], serviceName, "*", tokenString[:maxTokenLength]) @@ -3149,7 +3153,7 @@ func userhostHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res returnedClients := make(ClientSet) var tl utils.TokenLineBuilder - tl.Initialize(400, " ") + tl.Initialize(maxLastArgLength, " ") for i, nickname := range msg.Params { if i >= 10 { break diff --git a/irc/server.go b/irc/server.go index 341623e1..955a9337 100644 --- a/irc/server.go +++ b/irc/server.go @@ -506,7 +506,9 @@ func (client *Client) getWhoisOf(target *Client, hasPrivs bool, rb *ResponseBuff whoischannels := client.whoisChannelsNames(target, rb.session.capabilities.Has(caps.MultiPrefix), oper.HasRoleCapab("sajoin")) if whoischannels != nil { - rb.Add(nil, client.server.name, RPL_WHOISCHANNELS, cnick, tnick, strings.Join(whoischannels, " ")) + for _, line := range utils.BuildTokenLines(maxLastArgLength, whoischannels, " ") { + rb.Add(nil, client.server.name, RPL_WHOISCHANNELS, cnick, tnick, line) + } } if target.HasMode(modes.Operator) && operStatusVisible(client, target, oper != nil) { tOper := target.Oper()