Przeglądaj źródła

config: Advertise STS draft, fix subsequent REHASHing

tags/v0.7.0
Daniel Oaks 7 lat temu
rodzic
commit
5c38800a02
5 zmienionych plików z 122 dodań i 9 usunięć
  1. 5
    3
      CHANGELOG.md
  2. 3
    1
      irc/capability.go
  3. 33
    2
      irc/config.go
  4. 63
    3
      irc/server.go
  5. 18
    0
      oragono.yaml

+ 5
- 3
CHANGELOG.md Wyświetl plik

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

+ 3
- 1
irc/capability.go Wyświetl plik

@@ -28,6 +28,7 @@ const (
28 28
 	MultiPrefix     Capability = "multi-prefix"
29 29
 	SASL            Capability = "sasl"
30 30
 	ServerTime      Capability = "server-time"
31
+	STS             Capability = "draft/sts"
31 32
 	UserhostInNames Capability = "userhost-in-names"
32 33
 )
33 34
 
@@ -46,7 +47,8 @@ var (
46 47
 		MessageTags: true,
47 48
 		MultiPrefix: true,
48 49
 		// SASL is set during server startup
49
-		ServerTime:      true,
50
+		ServerTime: true,
51
+		// STS is set during server startup
50 52
 		UserhostInNames: true,
51 53
 	}
52 54
 	CapValues = map[Capability]string{

+ 33
- 2
irc/config.go Wyświetl plik

@@ -14,6 +14,7 @@ import (
14 14
 	"strings"
15 15
 	"time"
16 16
 
17
+	"github.com/DanielOaks/oragono/irc/custime"
17 18
 	"gopkg.in/yaml.v2"
18 19
 )
19 20
 
@@ -132,6 +133,26 @@ type LineLenConfig struct {
132 133
 	Rest int
133 134
 }
134 135
 
136
+type STSConfig struct {
137
+	Enabled        bool
138
+	Duration       time.Duration `yaml:"duration-real"`
139
+	DurationString string        `yaml:"duration"`
140
+	Port           int
141
+	Preload        bool
142
+}
143
+
144
+// Value returns the STS value to advertise in CAP
145
+func (sts *STSConfig) Value() string {
146
+	val := fmt.Sprintf("duration=%d,", int(sts.Duration.Seconds()))
147
+	if sts.Enabled && sts.Port > 0 {
148
+		val += fmt.Sprintf(",port=%d", sts.Port)
149
+	}
150
+	if sts.Enabled && sts.Preload {
151
+		val += ",preload"
152
+	}
153
+	return val
154
+}
155
+
135 156
 type Config struct {
136 157
 	Network struct {
137 158
 		Name string
@@ -144,8 +165,9 @@ type Config struct {
144 165
 		Listen             []string
145 166
 		Wslisten           string                      `yaml:"ws-listen"`
146 167
 		TLSListeners       map[string]*TLSListenConfig `yaml:"tls-listeners"`
147
-		RestAPI            RestAPIConfig               `yaml:"rest-api"`
148
-		CheckIdent         bool                        `yaml:"check-ident"`
168
+		STS                STSConfig
169
+		RestAPI            RestAPIConfig `yaml:"rest-api"`
170
+		CheckIdent         bool          `yaml:"check-ident"`
149 171
 		MOTD               string
150 172
 		ConnectionLimits   ConnectionLimitsConfig   `yaml:"connection-limits"`
151 173
 		ConnectionThrottle ConnectionThrottleConfig `yaml:"connection-throttling"`
@@ -342,6 +364,15 @@ func LoadConfig(filename string) (config *Config, err error) {
342 364
 	if config.Limits.NickLen < 1 || config.Limits.ChannelLen < 2 || config.Limits.AwayLen < 1 || config.Limits.KickLen < 1 || config.Limits.TopicLen < 1 {
343 365
 		return nil, errors.New("Limits aren't setup properly, check them and make them sane")
344 366
 	}
367
+	if config.Server.STS.Enabled {
368
+		config.Server.STS.Duration, err = custime.ParseDuration(config.Server.STS.DurationString)
369
+		if err != nil {
370
+			return nil, fmt.Errorf("Could not parse STS duration: %s", err.Error())
371
+		}
372
+		if config.Server.STS.Port < 0 || config.Server.STS.Port > 65535 {
373
+			return nil, fmt.Errorf("STS port is incorrect, should be 0 if disabled: %d", config.Server.STS.Port)
374
+		}
375
+	}
345 376
 	if config.Server.ConnectionThrottle.Enabled {
346 377
 		config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString)
347 378
 		if err != nil {

+ 63
- 3
irc/server.go Wyświetl plik

@@ -118,6 +118,7 @@ type Server struct {
118 118
 	restAPI                      *RestAPIConfig
119 119
 	signals                      chan os.Signal
120 120
 	store                        *buntdb.DB
121
+	stsEnabled                   bool
121 122
 	whoWas                       *WhoWasList
122 123
 }
123 124
 
@@ -154,6 +155,11 @@ func NewServer(configFilename string, config *Config, logger *Logger) (*Server,
154 155
 		SupportedCapabilities[SASL] = true
155 156
 	}
156 157
 
158
+	if config.Server.STS.Enabled {
159
+		SupportedCapabilities[STS] = true
160
+		CapValues[STS] = config.Server.STS.Value()
161
+	}
162
+
157 163
 	if config.Limits.LineLen.Tags > 512 || config.Limits.LineLen.Rest > 512 {
158 164
 		SupportedCapabilities[MaxLine] = true
159 165
 		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,
212 218
 		operclasses:    *operClasses,
213 219
 		operators:      opers,
214 220
 		signals:        make(chan os.Signal, len(ServerExitSignals)),
221
+		stsEnabled:     config.Server.STS.Enabled,
215 222
 		rehashSignal:   make(chan os.Signal, 1),
216 223
 		restAPI:        &config.Server.RestAPI,
217 224
 		whoWas:         NewWhoWasList(config.Limits.WhowasEntries),
@@ -1234,8 +1241,13 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1234 1241
 
1235 1242
 // rehash reloads the config and applies the changes from the config file.
1236 1243
 func (server *Server) rehash() error {
1244
+	server.logger.Log(LogDebug, "rehash", "Starting rehash")
1245
+
1237 1246
 	// only let one REHASH go on at a time
1238 1247
 	server.rehashMutex.Lock()
1248
+	defer server.rehashMutex.Unlock()
1249
+
1250
+	server.logger.Log(LogDebug, "rehash", "Got rehash lock")
1239 1251
 
1240 1252
 	config, err := LoadConfig(server.configFilename)
1241 1253
 
@@ -1290,11 +1302,13 @@ func (server *Server) rehash() error {
1290 1302
 		}
1291 1303
 	}
1292 1304
 	server.clients.ByNickMutex.RUnlock()
1305
+	server.connectionThrottleMutex.Unlock()
1293 1306
 	server.connectionLimitsMutex.Unlock()
1294 1307
 
1295 1308
 	// setup new and removed caps
1296 1309
 	addedCaps := make(CapabilitySet)
1297 1310
 	removedCaps := make(CapabilitySet)
1311
+	updatedCaps := make(CapabilitySet)
1298 1312
 
1299 1313
 	// SASL
1300 1314
 	if config.Accounts.AuthenticationEnabled && !server.accountAuthenticationEnabled {
@@ -1309,11 +1323,42 @@ func (server *Server) rehash() error {
1309 1323
 	}
1310 1324
 	server.accountAuthenticationEnabled = config.Accounts.AuthenticationEnabled
1311 1325
 
1326
+	// STS
1327
+	stsValue := config.Server.STS.Value()
1328
+	var stsDisabled bool
1329
+	server.logger.Log(LogDebug, "rehash", "STS Vals", CapValues[STS], stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled))
1330
+	if config.Server.STS.Enabled && !server.stsEnabled {
1331
+		// enabling STS
1332
+		SupportedCapabilities[STS] = true
1333
+		addedCaps[STS] = true
1334
+		CapValues[STS] = stsValue
1335
+	} else if !config.Server.STS.Enabled && server.stsEnabled {
1336
+		// disabling STS
1337
+		SupportedCapabilities[STS] = false
1338
+		removedCaps[STS] = true
1339
+		stsDisabled = true
1340
+	} else if config.Server.STS.Enabled && server.stsEnabled && stsValue != CapValues[STS] {
1341
+		// STS policy updated
1342
+		CapValues[STS] = stsValue
1343
+		updatedCaps[STS] = true
1344
+	}
1345
+	server.stsEnabled = config.Server.STS.Enabled
1346
+
1312 1347
 	// burst new and removed caps
1313 1348
 	var capBurstClients ClientSet
1314 1349
 	added := make(map[CapVersion]string)
1315 1350
 	var removed string
1316 1351
 
1352
+	// updated caps get DEL'd and then NEW'd
1353
+	// so, we can just add updated ones to both removed and added lists here and they'll be correctly handled
1354
+	server.logger.Log(LogDebug, "rehash", "Updated Caps", updatedCaps.String(Cap301), strconv.Itoa(len(updatedCaps)))
1355
+	if len(updatedCaps) > 0 {
1356
+		for capab := range updatedCaps {
1357
+			addedCaps[capab] = true
1358
+			removedCaps[capab] = true
1359
+		}
1360
+	}
1361
+
1317 1362
 	if len(addedCaps) > 0 || len(removedCaps) > 0 {
1318 1363
 		capBurstClients = server.clients.AllWithCaps(CapNotify)
1319 1364
 
@@ -1324,15 +1369,30 @@ func (server *Server) rehash() error {
1324 1369
 	}
1325 1370
 
1326 1371
 	for sClient := range capBurstClients {
1327
-		if len(addedCaps) > 0 {
1328
-			sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
1372
+		if stsDisabled {
1373
+			// remove STS policy
1374
+			//TODO(dan): this is an ugly hack. we can write this better.
1375
+			stsPolicy := "sts=duration=0"
1376
+			if len(addedCaps) > 0 {
1377
+				added[Cap302] = added[Cap302] + " " + stsPolicy
1378
+			} else {
1379
+				addedCaps[STS] = true
1380
+				added[Cap302] = stsPolicy
1381
+			}
1329 1382
 		}
1330 1383
 		if len(removedCaps) > 0 {
1331 1384
 			sClient.Send(nil, server.name, "CAP", sClient.nick, "DEL", removed)
1332 1385
 		}
1386
+		if len(addedCaps) > 0 {
1387
+			sClient.Send(nil, server.name, "CAP", sClient.nick, "NEW", added[sClient.capVersion])
1388
+		}
1333 1389
 	}
1334 1390
 
1335 1391
 	// set server options
1392
+	lineLenConfig := LineLenLimits{
1393
+		Tags: config.Limits.LineLen.Tags,
1394
+		Rest: config.Limits.LineLen.Rest,
1395
+	}
1336 1396
 	server.limits = Limits{
1337 1397
 		AwayLen:        int(config.Limits.AwayLen),
1338 1398
 		ChannelLen:     int(config.Limits.ChannelLen),
@@ -1341,6 +1401,7 @@ func (server *Server) rehash() error {
1341 1401
 		NickLen:        int(config.Limits.NickLen),
1342 1402
 		TopicLen:       int(config.Limits.TopicLen),
1343 1403
 		ChanListModes:  int(config.Limits.ChanListModes),
1404
+		LineLen:        lineLenConfig,
1344 1405
 	}
1345 1406
 	server.operclasses = *operclasses
1346 1407
 	server.operators = opers
@@ -1403,7 +1464,6 @@ func (server *Server) rehash() error {
1403 1464
 		}
1404 1465
 	}
1405 1466
 
1406
-	server.rehashMutex.Unlock()
1407 1467
 	return nil
1408 1468
 }
1409 1469
 

+ 18
- 0
oragono.yaml Wyświetl plik

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

Ładowanie…
Anuluj
Zapisz