mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 13:29:27 +01:00
config: Advertise STS draft, fix subsequent REHASHing
This commit is contained in:
parent
0675b09c88
commit
5c38800a02
@ -15,17 +15,19 @@ New release of Oragono!
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Added `USERHOST` command (thanks @vegax87).
|
* Added `USERHOST` command (thanks @vegax87).
|
||||||
|
* Added draft IRCv3 capability [draft/sts](http://ircv3.net/specs/core/sts-3.3.html).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Logging is now much better and useful.
|
* Logging is now much better and useful.
|
||||||
* Can now specify years, months and days (e.g. `1y12m30d`) with DLINE and KLINE.
|
* Can now specify years, months and days (e.g. `1y12m30d`) with DLINE and KLINE.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fixed an account issue where clients could login to multiple accounts at once.
|
* 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
|
## [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.
|
We've added a ton of new features in this release! Automated connection throttling, the ability to `KLINE`, updated casemapping and line-length specifications.
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ const (
|
|||||||
MultiPrefix Capability = "multi-prefix"
|
MultiPrefix Capability = "multi-prefix"
|
||||||
SASL Capability = "sasl"
|
SASL Capability = "sasl"
|
||||||
ServerTime Capability = "server-time"
|
ServerTime Capability = "server-time"
|
||||||
|
STS Capability = "draft/sts"
|
||||||
UserhostInNames Capability = "userhost-in-names"
|
UserhostInNames Capability = "userhost-in-names"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,7 +47,8 @@ var (
|
|||||||
MessageTags: true,
|
MessageTags: true,
|
||||||
MultiPrefix: true,
|
MultiPrefix: true,
|
||||||
// SASL is set during server startup
|
// SASL is set during server startup
|
||||||
ServerTime: true,
|
ServerTime: true,
|
||||||
|
// STS is set during server startup
|
||||||
UserhostInNames: true,
|
UserhostInNames: true,
|
||||||
}
|
}
|
||||||
CapValues = map[Capability]string{
|
CapValues = map[Capability]string{
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/DanielOaks/oragono/irc/custime"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -132,6 +133,26 @@ type LineLenConfig struct {
|
|||||||
Rest int
|
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 {
|
type Config struct {
|
||||||
Network struct {
|
Network struct {
|
||||||
Name string
|
Name string
|
||||||
@ -144,8 +165,9 @@ type Config struct {
|
|||||||
Listen []string
|
Listen []string
|
||||||
Wslisten string `yaml:"ws-listen"`
|
Wslisten string `yaml:"ws-listen"`
|
||||||
TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"`
|
TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"`
|
||||||
RestAPI RestAPIConfig `yaml:"rest-api"`
|
STS STSConfig
|
||||||
CheckIdent bool `yaml:"check-ident"`
|
RestAPI RestAPIConfig `yaml:"rest-api"`
|
||||||
|
CheckIdent bool `yaml:"check-ident"`
|
||||||
MOTD string
|
MOTD string
|
||||||
ConnectionLimits ConnectionLimitsConfig `yaml:"connection-limits"`
|
ConnectionLimits ConnectionLimitsConfig `yaml:"connection-limits"`
|
||||||
ConnectionThrottle ConnectionThrottleConfig `yaml:"connection-throttling"`
|
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 {
|
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")
|
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 {
|
if config.Server.ConnectionThrottle.Enabled {
|
||||||
config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString)
|
config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -118,6 +118,7 @@ type Server struct {
|
|||||||
restAPI *RestAPIConfig
|
restAPI *RestAPIConfig
|
||||||
signals chan os.Signal
|
signals chan os.Signal
|
||||||
store *buntdb.DB
|
store *buntdb.DB
|
||||||
|
stsEnabled bool
|
||||||
whoWas *WhoWasList
|
whoWas *WhoWasList
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +155,11 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
|
|||||||
SupportedCapabilities[SASL] = true
|
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 {
|
if config.Limits.LineLen.Tags > 512 || config.Limits.LineLen.Rest > 512 {
|
||||||
SupportedCapabilities[MaxLine] = true
|
SupportedCapabilities[MaxLine] = true
|
||||||
CapValues[MaxLine] = fmt.Sprintf("%d,%d", config.Limits.LineLen.Tags, config.Limits.LineLen.Rest)
|
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,
|
operclasses: *operClasses,
|
||||||
operators: opers,
|
operators: opers,
|
||||||
signals: make(chan os.Signal, len(ServerExitSignals)),
|
signals: make(chan os.Signal, len(ServerExitSignals)),
|
||||||
|
stsEnabled: config.Server.STS.Enabled,
|
||||||
rehashSignal: make(chan os.Signal, 1),
|
rehashSignal: make(chan os.Signal, 1),
|
||||||
restAPI: &config.Server.RestAPI,
|
restAPI: &config.Server.RestAPI,
|
||||||
whoWas: NewWhoWasList(config.Limits.WhowasEntries),
|
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.
|
// rehash reloads the config and applies the changes from the config file.
|
||||||
func (server *Server) rehash() error {
|
func (server *Server) rehash() error {
|
||||||
|
server.logger.Log(LogDebug, "rehash", "Starting rehash")
|
||||||
|
|
||||||
// only let one REHASH go on at a time
|
// only let one REHASH go on at a time
|
||||||
server.rehashMutex.Lock()
|
server.rehashMutex.Lock()
|
||||||
|
defer server.rehashMutex.Unlock()
|
||||||
|
|
||||||
|
server.logger.Log(LogDebug, "rehash", "Got rehash lock")
|
||||||
|
|
||||||
config, err := LoadConfig(server.configFilename)
|
config, err := LoadConfig(server.configFilename)
|
||||||
|
|
||||||
@ -1290,11 +1302,13 @@ func (server *Server) rehash() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
server.clients.ByNickMutex.RUnlock()
|
server.clients.ByNickMutex.RUnlock()
|
||||||
|
server.connectionThrottleMutex.Unlock()
|
||||||
server.connectionLimitsMutex.Unlock()
|
server.connectionLimitsMutex.Unlock()
|
||||||
|
|
||||||
// setup new and removed caps
|
// setup new and removed caps
|
||||||
addedCaps := make(CapabilitySet)
|
addedCaps := make(CapabilitySet)
|
||||||
removedCaps := make(CapabilitySet)
|
removedCaps := make(CapabilitySet)
|
||||||
|
updatedCaps := make(CapabilitySet)
|
||||||
|
|
||||||
// SASL
|
// SASL
|
||||||
if config.Accounts.AuthenticationEnabled && !server.accountAuthenticationEnabled {
|
if config.Accounts.AuthenticationEnabled && !server.accountAuthenticationEnabled {
|
||||||
@ -1309,11 +1323,42 @@ func (server *Server) rehash() error {
|
|||||||
}
|
}
|
||||||
server.accountAuthenticationEnabled = config.Accounts.AuthenticationEnabled
|
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
|
// burst new and removed caps
|
||||||
var capBurstClients ClientSet
|
var capBurstClients ClientSet
|
||||||
added := make(map[CapVersion]string)
|
added := make(map[CapVersion]string)
|
||||||
var removed 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 {
|
if len(addedCaps) > 0 || len(removedCaps) > 0 {
|
||||||
capBurstClients = server.clients.AllWithCaps(CapNotify)
|
capBurstClients = server.clients.AllWithCaps(CapNotify)
|
||||||
|
|
||||||
@ -1324,15 +1369,30 @@ func (server *Server) rehash() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for sClient := range capBurstClients {
|
for sClient := range capBurstClients {
|
||||||
if len(addedCaps) > 0 {
|
if stsDisabled {
|
||||||
sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
|
// 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 {
|
if len(removedCaps) > 0 {
|
||||||
sClient.Send(nil, server.name, "CAP", sClient.nick, "DEL", removed)
|
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
|
// set server options
|
||||||
|
lineLenConfig := LineLenLimits{
|
||||||
|
Tags: config.Limits.LineLen.Tags,
|
||||||
|
Rest: config.Limits.LineLen.Rest,
|
||||||
|
}
|
||||||
server.limits = Limits{
|
server.limits = Limits{
|
||||||
AwayLen: int(config.Limits.AwayLen),
|
AwayLen: int(config.Limits.AwayLen),
|
||||||
ChannelLen: int(config.Limits.ChannelLen),
|
ChannelLen: int(config.Limits.ChannelLen),
|
||||||
@ -1341,6 +1401,7 @@ func (server *Server) rehash() error {
|
|||||||
NickLen: int(config.Limits.NickLen),
|
NickLen: int(config.Limits.NickLen),
|
||||||
TopicLen: int(config.Limits.TopicLen),
|
TopicLen: int(config.Limits.TopicLen),
|
||||||
ChanListModes: int(config.Limits.ChanListModes),
|
ChanListModes: int(config.Limits.ChanListModes),
|
||||||
|
LineLen: lineLenConfig,
|
||||||
}
|
}
|
||||||
server.operclasses = *operclasses
|
server.operclasses = *operclasses
|
||||||
server.operators = opers
|
server.operators = opers
|
||||||
@ -1403,7 +1464,6 @@ func (server *Server) rehash() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.rehashMutex.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
oragono.yaml
18
oragono.yaml
@ -26,6 +26,24 @@ server:
|
|||||||
":6697":
|
":6697":
|
||||||
key: tls.key
|
key: tls.key
|
||||||
cert: tls.crt
|
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 management API, for use with web interface
|
||||||
rest-api:
|
rest-api:
|
||||||
|
Loading…
Reference in New Issue
Block a user