瀏覽代碼

factor out confirmation codes into utils, change their format

tags/v2.0.0-rc1
Shivaram Lingamneni 4 年之前
父節點
當前提交
85a536977c
共有 5 個文件被更改,包括 63 次插入15 次删除
  1. 3
    13
      irc/chanserv.go
  2. 1
    1
      irc/handlers.go
  3. 1
    1
      irc/nickserv.go
  4. 22
    0
      irc/utils/confirmation.go
  5. 36
    0
      irc/utils/confirmation_test.go

+ 3
- 13
irc/chanserv.go 查看文件

@@ -4,17 +4,15 @@
4 4
 package irc
5 5
 
6 6
 import (
7
-	"bytes"
8 7
 	"fmt"
9
-	"hash/crc32"
10 8
 	"sort"
11
-	"strconv"
12 9
 	"strings"
13 10
 	"time"
14 11
 
15 12
 	"github.com/goshuirc/irc-go/ircfmt"
16 13
 	"github.com/oragono/oragono/irc/modes"
17 14
 	"github.com/oragono/oragono/irc/sno"
15
+	"github.com/oragono/oragono/irc/utils"
18 16
 )
19 17
 
20 18
 const chanservHelp = `ChanServ lets you register and manage channels.`
@@ -352,7 +350,7 @@ func csUnregisterHandler(server *Server, client *Client, command string, params
352 350
 	}
353 351
 
354 352
 	info := channel.ExportRegistration(0)
355
-	expectedCode := unregisterConfirmationCode(info.Name, info.RegisteredAt)
353
+	expectedCode := utils.ConfirmationCode(info.Name, info.RegisteredAt)
356 354
 	if expectedCode != verificationCode {
357 355
 		csNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this channel will remove all stored channel attributes.$b")))
358 356
 		csNotice(rb, fmt.Sprintf(client.t("To confirm channel unregistration, type: /CS UNREGISTER %[1]s %[2]s"), channelKey, expectedCode))
@@ -363,14 +361,6 @@ func csUnregisterHandler(server *Server, client *Client, command string, params
363 361
 	csNotice(rb, fmt.Sprintf(client.t("Channel %s is now unregistered"), channelKey))
364 362
 }
365 363
 
366
-// deterministically generates a confirmation code for unregistering a channel / account
367
-func unregisterConfirmationCode(name string, registeredAt time.Time) (code string) {
368
-	var codeInput bytes.Buffer
369
-	codeInput.WriteString(name)
370
-	codeInput.WriteString(strconv.FormatInt(registeredAt.Unix(), 16))
371
-	return strconv.Itoa(int(crc32.ChecksumIEEE(codeInput.Bytes())))
372
-}
373
-
374 364
 func csClearHandler(server *Server, client *Client, command string, params []string, rb *ResponseBuffer) {
375 365
 	channel := server.channels.Get(params[0])
376 366
 	if channel == nil {
@@ -426,7 +416,7 @@ func csTransferHandler(server *Server, client *Client, command string, params []
426 416
 		return
427 417
 	}
428 418
 	if targetAccount.NameCasefolded != account {
429
-		expectedCode := unregisterConfirmationCode(regInfo.Name, regInfo.RegisteredAt)
419
+		expectedCode := utils.ConfirmationCode(regInfo.Name, regInfo.RegisteredAt)
430 420
 		codeValidated := 2 < len(params) && params[2] == expectedCode
431 421
 		if !codeValidated {
432 422
 			csNotice(rb, ircfmt.Unescape(client.t("$bWarning: you are about to transfer control of your channel to another user.$b")))

+ 1
- 1
irc/handlers.go 查看文件

@@ -810,7 +810,7 @@ func debugHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
810 810
 			rb.Notice(client.t("You must have rehash permissions in order to execute DEBUG CRASHSERVER"))
811 811
 			return false
812 812
 		}
813
-		code := unregisterConfirmationCode(server.name, server.ctime)
813
+		code := utils.ConfirmationCode(server.name, server.ctime)
814 814
 		if len(msg.Params) == 1 || msg.Params[1] != code {
815 815
 			rb.Notice(fmt.Sprintf(client.t("To crash the server, issue the following command: /DEBUG CRASHSERVER %s"), code))
816 816
 			return false

+ 1
- 1
irc/nickserv.go 查看文件

@@ -732,7 +732,7 @@ func nsUnregisterHandler(server *Server, client *Client, command string, params
732 732
 		return
733 733
 	}
734 734
 
735
-	expectedCode := unregisterConfirmationCode(account.Name, account.RegisteredAt)
735
+	expectedCode := utils.ConfirmationCode(account.Name, account.RegisteredAt)
736 736
 	if expectedCode != verificationCode {
737 737
 		nsNotice(rb, ircfmt.Unescape(client.t("$bWarning: unregistering this account will remove its stored privileges.$b")))
738 738
 		nsNotice(rb, fmt.Sprintf(client.t("To confirm account unregistration, type: /NS UNREGISTER %[1]s %[2]s"), cfname, expectedCode))

+ 22
- 0
irc/utils/confirmation.go 查看文件

@@ -0,0 +1,22 @@
1
+// Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
2
+// released under the MIT license
3
+
4
+package utils
5
+
6
+import (
7
+	"crypto/sha256"
8
+	"encoding/binary"
9
+	"time"
10
+)
11
+
12
+// Deterministically generates a confirmation code for some destructive activity;
13
+// `name` is typically the name of the identity being destroyed (a channel being
14
+// unregistered, or the server being crashed) and `createdAt` means a different
15
+// value is required each time.
16
+func ConfirmationCode(name string, createdAt time.Time) (code string) {
17
+	buf := make([]byte, len(name)+8)
18
+	binary.BigEndian.PutUint64(buf, uint64(createdAt.UnixNano()))
19
+	copy(buf[8:], name[:])
20
+	out := sha256.Sum256(buf)
21
+	return B32Encoder.EncodeToString(out[:3])
22
+}

+ 36
- 0
irc/utils/confirmation_test.go 查看文件

@@ -0,0 +1,36 @@
1
+// Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
2
+// released under the MIT license
3
+
4
+package utils
5
+
6
+import (
7
+	"testing"
8
+	"time"
9
+)
10
+
11
+func easyParse(timestamp string) time.Time {
12
+	result, err := time.Parse("2006-01-02 15:04:05Z", timestamp)
13
+	if err != nil {
14
+		panic(err)
15
+	}
16
+	return result
17
+}
18
+
19
+func TestConfirmation(t *testing.T) {
20
+	set := make(map[string]struct{})
21
+
22
+	set[ConfirmationCode("#darwin", easyParse("2006-01-01 00:00:00Z"))] = struct{}{}
23
+	set[ConfirmationCode("#darwin", easyParse("2006-01-02 00:00:00Z"))] = struct{}{}
24
+	set[ConfirmationCode("#xelpers", easyParse("2006-01-01 00:00:00Z"))] = struct{}{}
25
+	set[ConfirmationCode("#xelpers", easyParse("2006-01-02 00:00:00Z"))] = struct{}{}
26
+
27
+	if len(set) != 4 {
28
+		t.Error("confirmation codes are not unique")
29
+	}
30
+
31
+	for code := range set {
32
+		if len(code) <= 2 || len(code) >= 8 {
33
+			t.Errorf("bad code: %s", code)
34
+		}
35
+	}
36
+}

Loading…
取消
儲存