3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-10 22:19:31 +01:00

config: Advertise STS draft, fix subsequent REHASHing

This commit is contained in:
Daniel Oaks 2017-03-09 19:07:35 +10:00
parent 0675b09c88
commit 5c38800a02
5 changed files with 122 additions and 9 deletions

View File

@ -15,17 +15,19 @@ New release of Oragono!
### Added
* Added `USERHOST` command (thanks @vegax87).
* Added draft IRCv3 capability [draft/sts](http://ircv3.net/specs/core/sts-3.3.html).
### Changed
* Logging is now much better and useful.
* Can now specify years, months and days (e.g. `1y12m30d`) with DLINE and KLINE.
### Removed
### Fixed
* Fixed an account issue where clients could login to multiple accounts at once.
* Fixed issues that prevented rehashing after the first rehash had gone through successfully.
## [0.6.0] - 2017-01-19
We've added a ton of new features in this release! Automated connection throttling, the ability to `KLINE`, updated casemapping and line-length specifications.

View File

@ -28,6 +28,7 @@ const (
MultiPrefix Capability = "multi-prefix"
SASL Capability = "sasl"
ServerTime Capability = "server-time"
STS Capability = "draft/sts"
UserhostInNames Capability = "userhost-in-names"
)
@ -46,7 +47,8 @@ var (
MessageTags: true,
MultiPrefix: true,
// SASL is set during server startup
ServerTime: true,
ServerTime: true,
// STS is set during server startup
UserhostInNames: true,
}
CapValues = map[Capability]string{

View File

@ -14,6 +14,7 @@ import (
"strings"
"time"
"github.com/DanielOaks/oragono/irc/custime"
"gopkg.in/yaml.v2"
)
@ -132,6 +133,26 @@ type LineLenConfig struct {
Rest int
}
type STSConfig struct {
Enabled bool
Duration time.Duration `yaml:"duration-real"`
DurationString string `yaml:"duration"`
Port int
Preload bool
}
// Value returns the STS value to advertise in CAP
func (sts *STSConfig) Value() string {
val := fmt.Sprintf("duration=%d,", int(sts.Duration.Seconds()))
if sts.Enabled && sts.Port > 0 {
val += fmt.Sprintf(",port=%d", sts.Port)
}
if sts.Enabled && sts.Preload {
val += ",preload"
}
return val
}
type Config struct {
Network struct {
Name string
@ -144,8 +165,9 @@ type Config struct {
Listen []string
Wslisten string `yaml:"ws-listen"`
TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"`
RestAPI RestAPIConfig `yaml:"rest-api"`
CheckIdent bool `yaml:"check-ident"`
STS STSConfig
RestAPI RestAPIConfig `yaml:"rest-api"`
CheckIdent bool `yaml:"check-ident"`
MOTD string
ConnectionLimits ConnectionLimitsConfig `yaml:"connection-limits"`
ConnectionThrottle ConnectionThrottleConfig `yaml:"connection-throttling"`
@ -342,6 +364,15 @@ func LoadConfig(filename string) (config *Config, err error) {
if config.Limits.NickLen < 1 || config.Limits.ChannelLen < 2 || config.Limits.AwayLen < 1 || config.Limits.KickLen < 1 || config.Limits.TopicLen < 1 {
return nil, errors.New("Limits aren't setup properly, check them and make them sane")
}
if config.Server.STS.Enabled {
config.Server.STS.Duration, err = custime.ParseDuration(config.Server.STS.DurationString)
if err != nil {
return nil, fmt.Errorf("Could not parse STS duration: %s", err.Error())
}
if config.Server.STS.Port < 0 || config.Server.STS.Port > 65535 {
return nil, fmt.Errorf("STS port is incorrect, should be 0 if disabled: %d", config.Server.STS.Port)
}
}
if config.Server.ConnectionThrottle.Enabled {
config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString)
if err != nil {

View File

@ -118,6 +118,7 @@ type Server struct {
restAPI *RestAPIConfig
signals chan os.Signal
store *buntdb.DB
stsEnabled bool
whoWas *WhoWasList
}
@ -154,6 +155,11 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
SupportedCapabilities[SASL] = true
}
if config.Server.STS.Enabled {
SupportedCapabilities[STS] = true
CapValues[STS] = config.Server.STS.Value()
}
if config.Limits.LineLen.Tags > 512 || config.Limits.LineLen.Rest > 512 {
SupportedCapabilities[MaxLine] = true
CapValues[MaxLine] = fmt.Sprintf("%d,%d", config.Limits.LineLen.Tags, config.Limits.LineLen.Rest)
@ -212,6 +218,7 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
operclasses: *operClasses,
operators: opers,
signals: make(chan os.Signal, len(ServerExitSignals)),
stsEnabled: config.Server.STS.Enabled,
rehashSignal: make(chan os.Signal, 1),
restAPI: &config.Server.RestAPI,
whoWas: NewWhoWasList(config.Limits.WhowasEntries),
@ -1234,8 +1241,13 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// rehash reloads the config and applies the changes from the config file.
func (server *Server) rehash() error {
server.logger.Log(LogDebug, "rehash", "Starting rehash")
// only let one REHASH go on at a time
server.rehashMutex.Lock()
defer server.rehashMutex.Unlock()
server.logger.Log(LogDebug, "rehash", "Got rehash lock")
config, err := LoadConfig(server.configFilename)
@ -1290,11 +1302,13 @@ func (server *Server) rehash() error {
}
}
server.clients.ByNickMutex.RUnlock()
server.connectionThrottleMutex.Unlock()
server.connectionLimitsMutex.Unlock()
// setup new and removed caps
addedCaps := make(CapabilitySet)
removedCaps := make(CapabilitySet)
updatedCaps := make(CapabilitySet)
// SASL
if config.Accounts.AuthenticationEnabled && !server.accountAuthenticationEnabled {
@ -1309,11 +1323,42 @@ func (server *Server) rehash() error {
}
server.accountAuthenticationEnabled = config.Accounts.AuthenticationEnabled
// STS
stsValue := config.Server.STS.Value()
var stsDisabled bool
server.logger.Log(LogDebug, "rehash", "STS Vals", CapValues[STS], stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled))
if config.Server.STS.Enabled && !server.stsEnabled {
// enabling STS
SupportedCapabilities[STS] = true
addedCaps[STS] = true
CapValues[STS] = stsValue
} else if !config.Server.STS.Enabled && server.stsEnabled {
// disabling STS
SupportedCapabilities[STS] = false
removedCaps[STS] = true
stsDisabled = true
} else if config.Server.STS.Enabled && server.stsEnabled && stsValue != CapValues[STS] {
// STS policy updated
CapValues[STS] = stsValue
updatedCaps[STS] = true
}
server.stsEnabled = config.Server.STS.Enabled
// burst new and removed caps
var capBurstClients ClientSet
added := make(map[CapVersion]string)
var removed string
// updated caps get DEL'd and then NEW'd
// so, we can just add updated ones to both removed and added lists here and they'll be correctly handled
server.logger.Log(LogDebug, "rehash", "Updated Caps", updatedCaps.String(Cap301), strconv.Itoa(len(updatedCaps)))
if len(updatedCaps) > 0 {
for capab := range updatedCaps {
addedCaps[capab] = true
removedCaps[capab] = true
}
}
if len(addedCaps) > 0 || len(removedCaps) > 0 {
capBurstClients = server.clients.AllWithCaps(CapNotify)
@ -1324,15 +1369,30 @@ func (server *Server) rehash() error {
}
for sClient := range capBurstClients {
if len(addedCaps) > 0 {
sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
if stsDisabled {
// remove STS policy
//TODO(dan): this is an ugly hack. we can write this better.
stsPolicy := "sts=duration=0"
if len(addedCaps) > 0 {
added[Cap302] = added[Cap302] + " " + stsPolicy
} else {
addedCaps[STS] = true
added[Cap302] = stsPolicy
}
}
if len(removedCaps) > 0 {
sClient.Send(nil, server.name, "CAP", sClient.nick, "DEL", removed)
}
if len(addedCaps) > 0 {
sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
}
}
// set server options
lineLenConfig := LineLenLimits{
Tags: config.Limits.LineLen.Tags,
Rest: config.Limits.LineLen.Rest,
}
server.limits = Limits{
AwayLen: int(config.Limits.AwayLen),
ChannelLen: int(config.Limits.ChannelLen),
@ -1341,6 +1401,7 @@ func (server *Server) rehash() error {
NickLen: int(config.Limits.NickLen),
TopicLen: int(config.Limits.TopicLen),
ChanListModes: int(config.Limits.ChanListModes),
LineLen: lineLenConfig,
}
server.operclasses = *operclasses
server.operators = opers
@ -1403,7 +1464,6 @@ func (server *Server) rehash() error {
}
}
server.rehashMutex.Unlock()
return nil
}

View File

@ -26,6 +26,24 @@ server:
":6697":
key: tls.key
cert: tls.crt
# strict transport security, to get clients to automagically use TLS
sts:
# whether to advertise STS
#
# to stop advertising STS, leave this enabled and set 'duration' below to "0". this will
# advertise to connecting users that the STS policy they have saved is no longer valid
enabled: true
# how long clients should be forced to use TLS for.
# setting this to a too-long time will mean bad things if you later remove your TLS
duration: 0
# tls port - you should be listening on this port above
port: 6697
# should clients include this STS policy when they ship their inbuilt preload lists?
preload: false
# rest management API, for use with web interface
rest-api: