diff --git a/irc/client.go b/irc/client.go index 7e2ead9c..1dd44b91 100644 --- a/irc/client.go +++ b/irc/client.go @@ -195,6 +195,15 @@ type MultilineBatch struct { tags map[string]string } +// is this session connected in a way that could, in principle, allow certfp authentication? +// see #774 +func (s *Session) IsCertFPCapable() bool { + conn := s.socket.conn.UnderlyingConn() + // no client certs on websockets: + // https://bugs.chromium.org/p/chromium/issues/detail?id=329884 + return conn.Config.TLSConfig != nil && !conn.Config.WebSocket +} + // Starts a multiline batch, failing if there's one already open func (s *Session) StartMultilineBatch(label, target, responseLabel string, tags map[string]string) (err error) { if s.batch.label != "" { diff --git a/irc/config.go b/irc/config.go index 75fd1f27..b9509e99 100644 --- a/irc/config.go +++ b/irc/config.go @@ -591,6 +591,7 @@ type Config struct { supportedCaps *caps.Set supportedCapsWithoutSTS *caps.Set capValues caps.Values + capValuesNoExternal caps.Values Casemapping Casemapping EnforceUtf8 bool `yaml:"enforce-utf8"` OutputPath string `yaml:"output-path"` @@ -1388,7 +1389,7 @@ func LoadConfig(filename string) (config *Config, err error) { config.Accounts.VHosts.validRegexp = defaultValidVhostRegex } - saslCapValue := "PLAIN,EXTERNAL,SCRAM-SHA-256" + saslCapValue := "PLAIN,SCRAM-SHA-256,EXTERNAL" // TODO(#1782) clean this up: if !config.Accounts.AdvertiseSCRAM { saslCapValue = "PLAIN,EXTERNAL" @@ -1544,6 +1545,9 @@ func LoadConfig(filename string) (config *Config, err error) { config.Server.supportedCapsWithoutSTS.Union(config.Server.supportedCaps) config.Server.supportedCapsWithoutSTS.Disable(caps.STS) + config.Server.capValuesNoExternal = utils.CopyMap(config.Server.capValues) + config.Server.capValuesNoExternal[caps.SASL] = strings.TrimSuffix(saslCapValue, ",EXTERNAL") + return config, nil } diff --git a/irc/handlers.go b/irc/handlers.go index 75f2d54f..73a76365 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -591,7 +591,11 @@ func capHandler(server *Server, client *Client, msg ircmsg.Message, rb *Response rb.session.capVersion = newVersion } } - sendCapLines(supportedCaps, config.Server.capValues) + capValues := config.Server.capValues + if !rb.session.IsCertFPCapable() { + capValues = config.Server.capValuesNoExternal + } + sendCapLines(supportedCaps, capValues) case "LIST": // values not sent on LIST