diff --git a/default.yaml b/default.yaml index 87a91a57..c97a2b84 100644 --- a/default.yaml +++ b/default.yaml @@ -58,6 +58,8 @@ server: # always send a PROXY protocol header ahead of the connection. See the # manual ("Reverse proxies") for more details. proxy: false + # set the minimum TLS version: + min-tls-version: 1.2 # Example of a Unix domain socket for proxying: # "/tmp/oragono_sock": diff --git a/irc/channelmanager.go b/irc/channelmanager.go index 72ce0183..671020e3 100644 --- a/irc/channelmanager.go +++ b/irc/channelmanager.go @@ -176,6 +176,10 @@ func (cm *ChannelManager) maybeCleanup(channel *Channel, afterJoin bool) { return } + cm.maybeCleanupInternal(cfname, entry, afterJoin) +} + +func (cm *ChannelManager) maybeCleanupInternal(cfname string, entry *channelManagerEntry, afterJoin bool) { if afterJoin { entry.pendingJoins -= 1 } @@ -288,6 +292,9 @@ func (cm *ChannelManager) SetUnregistered(channelName string, account string) (e entry.skeleton = skel cm.chans[cfname] = entry } + // #1619: if the channel has 0 members and was only being retained + // because it was registered, clean it up: + cm.maybeCleanupInternal(cfname, entry, false) } return nil } diff --git a/irc/config.go b/irc/config.go index d421a073..1e7e8686 100644 --- a/irc/config.go +++ b/irc/config.go @@ -59,6 +59,7 @@ type listenerConfigBlock struct { TLS TLSListenConfig // SNI configuration, with multiple certificates: TLSCertificates []TLSListenConfig `yaml:"tls-certificates"` + MinTLSVersion string `yaml:"min-tls-version"` Proxy bool Tor bool STSOnly bool `yaml:"sts-only"` @@ -881,10 +882,29 @@ func loadTlsConfig(config listenerConfigBlock) (tlsConfig *tls.Config, err error result := tls.Config{ Certificates: certificates, ClientAuth: clientAuth, + MinVersion: tlsMinVersionFromString(config.MinTLSVersion), } return &result, nil } +func tlsMinVersionFromString(version string) uint16 { + version = strings.ToLower(version) + version = strings.TrimPrefix(version, "v") + switch version { + case "1", "1.0": + return tls.VersionTLS10 + case "1.1": + return tls.VersionTLS11 + case "1.2": + return tls.VersionTLS12 + case "1.3": + return tls.VersionTLS13 + default: + // tls package will fill in a sane value, currently 1.0 + return 0 + } +} + func loadCertWithLeaf(certFile, keyFile string) (cert tls.Certificate, err error) { // LoadX509KeyPair: "On successful return, Certificate.Leaf will be nil because // the parsed form of the certificate is not retained." tls.Config: @@ -1477,11 +1497,6 @@ func LoadConfig(filename string) (config *Config, err error) { return nil, err } - err = config.prepareListeners() - if err != nil { - return nil, fmt.Errorf("failed to prepare listeners: %v", err) - } - // #1428: Tor listeners should never see STS config.Server.supportedCapsWithoutSTS = caps.NewSet() config.Server.supportedCapsWithoutSTS.Union(config.Server.supportedCaps) diff --git a/irc/modes.go b/irc/modes.go index 414a8ebd..c4c4beb7 100644 --- a/irc/modes.go +++ b/irc/modes.go @@ -32,6 +32,9 @@ var ( // to confirm that the client actually has a valid operclass) func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, oper *Oper) modes.ModeChanges { applied := make(modes.ModeChanges, 0) + // #1617: if the user is offline, they are not counted in LUSERS, + // so don't modify the LUSERS stats for +i or +o. + present := len(client.Sessions()) != 0 for _, change := range changes { if change.Mode != modes.ServerNotice { @@ -42,9 +45,9 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, } if client.SetMode(change.Mode, true) { - if change.Mode == modes.Invisible { + if change.Mode == modes.Invisible && present { client.server.stats.ChangeInvisible(1) - } else if change.Mode == modes.Operator { + } else if change.Mode == modes.Operator && present { client.server.stats.ChangeOperators(1) } applied = append(applied, change) @@ -53,11 +56,13 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, case modes.Remove: var removedSnomasks string if client.SetMode(change.Mode, false) { - if change.Mode == modes.Invisible { + if change.Mode == modes.Invisible && present { client.server.stats.ChangeInvisible(-1) } else if change.Mode == modes.Operator { removedSnomasks = client.server.snomasks.String(client) - client.server.stats.ChangeOperators(-1) + if present { + client.server.stats.ChangeOperators(-1) + } applyOper(client, nil, nil) if removedSnomasks != "" { client.server.snomasks.RemoveClient(client) @@ -86,7 +91,7 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, if len(addMasks) != 0 { oper := client.Oper() // #1176: require special operator privileges to subscribe to snomasks - if oper.HasRoleCapab("snomasks") || oper.HasRoleCapab("ban") { + if force || oper.HasRoleCapab("snomasks") || oper.HasRoleCapab("ban") { success = true client.server.snomasks.AddMasks(client, addMasks...) } diff --git a/irctest b/irctest index 5e622a34..322cb7ae 160000 --- a/irctest +++ b/irctest @@ -1 +1 @@ -Subproject commit 5e622a34d38be329aec98b3b983a239fe3e1b4b7 +Subproject commit 322cb7ae26a2a94a0daec5458373319fa4e0e743 diff --git a/traditional.yaml b/traditional.yaml index 47601ac4..92d95728 100644 --- a/traditional.yaml +++ b/traditional.yaml @@ -32,6 +32,8 @@ server: # always send a PROXY protocol header ahead of the connection. See the # manual ("Reverse proxies") for more details. proxy: false + # optionally set the minimum TLS version (defaults to 1.0): + # min-tls-version: 1.2 # Example of a Unix domain socket for proxying: # "/tmp/oragono_sock":