diff --git a/irc/config.go b/irc/config.go index 67f2ec03..dce9f93b 100644 --- a/irc/config.go +++ b/irc/config.go @@ -728,7 +728,7 @@ type Config struct { Enabled bool MaxSubs int `yaml:"max-subs"` MaxKeys int `yaml:"max-keys"` - MaxValueBytes int `yaml:"max-value-length"` // todo: currently unenforced!! + MaxValueBytes int `yaml:"max-value-length"` } WebPush struct { diff --git a/irc/handlers.go b/irc/handlers.go index c2751a6f..dee168ef 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -20,6 +20,7 @@ import ( "strconv" "strings" "time" + "unicode/utf8" "github.com/ergochat/irc-go/ircfmt" "github.com/ergochat/irc-go/ircmsg" @@ -3104,7 +3105,8 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res originalTarget := msg.Params[0] target := originalTarget - if !server.Config().Metadata.Enabled { + config := server.Config() + if !config.Metadata.Enabled { rb.Add(nil, server.name, "FAIL", "METADATA", "FORBIDDEN", originalTarget, "Metadata is disabled on this server") return } @@ -3164,9 +3166,15 @@ func metadataHandler(server *Server, client *Client, msg ircmsg.Message, rb *Res if len(msg.Params) > 3 { value := msg.Params[3] - const maxCombinedLen = 350 - if len(key)+len(value) > maxCombinedLen { + if !globalUtf8EnforcementSetting && !utf8.ValidString(value) { + rb.Add(nil, server.name, "FAIL", "METADATA", "VALUE_INVALID", client.t("METADATA values must be UTF-8")) + return + } + + if len(key)+len(value) > maxCombinedMetadataLenBytes || + (config.Metadata.MaxValueBytes > 0 && len(value) > config.Metadata.MaxValueBytes) { + rb.Add(nil, server.name, "FAIL", "METADATA", "VALUE_INVALID", client.t("Value is too long")) return } diff --git a/irc/metadata.go b/irc/metadata.go index 3c4584d5..22465d0c 100644 --- a/irc/metadata.go +++ b/irc/metadata.go @@ -11,6 +11,11 @@ import ( "github.com/ergochat/ergo/irc/modes" ) +const ( + // metadata key + value need to be relayable on a single IRC RPL_KEYVALUE line + maxCombinedMetadataLenBytes = 350 +) + var ( errMetadataTooManySubs = errors.New("too many subscriptions") errMetadataNotFound = errors.New("key not found")