mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-28 23:19:30 +01:00
config: Advertise STS draft, fix subsequent REHASHing
This commit is contained in:
parent
0675b09c88
commit
5c38800a02
@ -15,6 +15,7 @@ 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.
|
||||
@ -24,6 +25,7 @@ New release of Oragono!
|
||||
|
||||
### 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
|
||||
|
@ -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"
|
||||
)
|
||||
|
||||
@ -47,6 +48,7 @@ var (
|
||||
MultiPrefix: true,
|
||||
// SASL is set during server startup
|
||||
ServerTime: true,
|
||||
// STS is set during server startup
|
||||
UserhostInNames: true,
|
||||
}
|
||||
CapValues = map[Capability]string{
|
||||
|
@ -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,6 +165,7 @@ type Config struct {
|
||||
Listen []string
|
||||
Wslisten string `yaml:"ws-listen"`
|
||||
TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"`
|
||||
STS STSConfig
|
||||
RestAPI RestAPIConfig `yaml:"rest-api"`
|
||||
CheckIdent bool `yaml:"check-ident"`
|
||||
MOTD string
|
||||
@ -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 {
|
||||
|
@ -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 stsDisabled {
|
||||
// remove STS policy
|
||||
//TODO(dan): this is an ugly hack. we can write this better.
|
||||
stsPolicy := "sts=duration=0"
|
||||
if len(addedCaps) > 0 {
|
||||
sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
|
||||
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
|
||||
}
|
||||
|
||||
|
18
oragono.yaml
18
oragono.yaml
@ -27,6 +27,24 @@ server:
|
||||
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:
|
||||
# whether the API is enabled or not
|
||||
|
Loading…
Reference in New Issue
Block a user