Parcourir la source

Restrict idents as other servers do

tags/v1.0.0-rc1
Daniel Oaks il y a 5 ans
Parent
révision
8cd5db1194
5 fichiers modifiés avec 49 ajouts et 4 suppressions
  1. 5
    2
      irc/client.go
  2. 1
    2
      irc/handlers.go
  3. 1
    0
      irc/numerics.go
  4. 26
    0
      irc/strings.go
  5. 16
    0
      irc/strings_test.go

+ 5
- 2
irc/client.go Voir le fichier

@@ -623,12 +623,15 @@ func (client *Client) HasUsername() bool {
623 623
 	return client.username != "" && client.username != "*"
624 624
 }
625 625
 
626
+// SetNames sets the client's ident and realname.
626 627
 func (client *Client) SetNames(username, realname string) error {
627
-	usernameCasefolded, err := CasefoldName(username)
628
-	if err != nil {
628
+	// do this before casefolding to ensure these are actually ascii
629
+	if !isIdent(username) {
629 630
 		return errInvalidUsername
630 631
 	}
631 632
 
633
+	usernameCasefolded := strings.ToLower(username) // only ascii is supported in idents anyway
634
+
632 635
 	client.stateMutex.Lock()
633 636
 	defer client.stateMutex.Unlock()
634 637
 

+ 1
- 2
irc/handlers.go Voir le fichier

@@ -2195,8 +2195,7 @@ func userHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
2195 2195
 
2196 2196
 	err := client.SetNames(msg.Params[0], msg.Params[3])
2197 2197
 	if err == errInvalidUsername {
2198
-		rb.Add(nil, "", "ERROR", client.t("Malformed username"))
2199
-		return true
2198
+		rb.Add(nil, server.name, ERR_INVALIDUSERNAME, client.t("Malformed username"))
2200 2199
 	}
2201 2200
 
2202 2201
 	return false

+ 1
- 0
irc/numerics.go Voir le fichier

@@ -143,6 +143,7 @@ const (
143 143
 	ERR_YOUREBANNEDCREEP            = "465"
144 144
 	ERR_YOUWILLBEBANNED             = "466"
145 145
 	ERR_KEYSET                      = "467"
146
+	ERR_INVALIDUSERNAME             = "468"
146 147
 	ERR_CHANNELISFULL               = "471"
147 148
 	ERR_UNKNOWNMODE                 = "472"
148 149
 	ERR_INVITEONLYCHAN              = "473"

+ 26
- 0
irc/strings.go Voir le fichier

@@ -128,6 +128,32 @@ func isBoring(name string) bool {
128 128
 	return true
129 129
 }
130 130
 
131
+// returns true if the given name is a valid ident, using a mix of Insp and
132
+// Chary's ident restrictions.
133
+func isIdent(name string) bool {
134
+	if len(name) < 1 {
135
+		return false
136
+	}
137
+
138
+	for i := 0; i < len(name); i++ {
139
+		chr := name[i]
140
+		if (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') {
141
+			continue // alphanumerics
142
+		}
143
+		if i == 0 {
144
+			return false // first char must be alnum
145
+		}
146
+		switch chr {
147
+		case '[', '\\', ']', '^', '_', '{', '|', '}', '-', '.', '`':
148
+			continue // allowed chars
149
+		default:
150
+			return false // disallowed chars
151
+		}
152
+	}
153
+
154
+	return true
155
+}
156
+
131 157
 // Skeleton produces a canonicalized identifier that tries to catch
132 158
 // homoglyphic / confusable identifiers. It's a tweaked version of the TR39
133 159
 // skeleton algorithm. We apply the skeleton algorithm first and only then casefold,

+ 16
- 0
irc/strings_test.go Voir le fichier

@@ -140,6 +140,22 @@ func TestIsBoring(t *testing.T) {
140 140
 	assertBoring("Νικηφόρος", false)
141 141
 }
142 142
 
143
+func TestIsIdent(t *testing.T) {
144
+	assertIdent := func(str string, expected bool) {
145
+		if isIdent(str) != expected {
146
+			t.Errorf("expected [%s] to have identness [%t], but got [%t]", str, expected, !expected)
147
+		}
148
+	}
149
+
150
+	assertIdent("warning", true)
151
+	assertIdent("sid3225", true)
152
+	assertIdent("dan.oak25", true)
153
+	assertIdent("dan.oak[25]", true)
154
+	assertIdent("phi@#$%ip", false)
155
+	assertIdent("Νικηφόρος", false)
156
+	assertIdent("-dan56", false)
157
+}
158
+
143 159
 func TestSkeleton(t *testing.T) {
144 160
 	skeleton := func(str string) string {
145 161
 		skel, err := Skeleton(str)

Chargement…
Annuler
Enregistrer