mirror of
https://github.com/mjl-/mox.git
synced 2025-07-10 09:54:40 +03:00
prevent unicode-confusion in password by applying PRECIS, and username/email address by applying unicode NFC normalization
an é (e with accent) can also be written as e+\u0301. the first form is NFC, the second NFD. when logging in, we transform usernames (email addresses) to NFC. so both forms will be accepted. if a client is using NFD, they can log in too. for passwords, we apply the PRECIS "opaquestring", which (despite the name) transforms the value too: unicode spaces are replaced with ascii spaces. the string is also normalized to NFC. PRECIS may reject confusing passwords when you set a password.
This commit is contained in:
@ -334,6 +334,9 @@ func startNoSwitchboard(t *testing.T) *testconn {
|
||||
return startArgs(t, false, false, true, false, "mjl")
|
||||
}
|
||||
|
||||
const password0 = "te\u0301st \u00a0\u2002\u200a" // NFD and various unicode spaces.
|
||||
const password1 = "tést " // PRECIS normalized, with NFC.
|
||||
|
||||
func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS, setPassword bool, accname string) *testconn {
|
||||
limitersInit() // Reset rate limiters.
|
||||
|
||||
@ -346,7 +349,7 @@ func startArgs(t *testing.T, first, isTLS, allowLoginWithoutTLS, setPassword boo
|
||||
acc, err := store.OpenAccount(pkglog, accname)
|
||||
tcheck(t, err, "open account")
|
||||
if setPassword {
|
||||
err = acc.SetPassword(pkglog, "testtest")
|
||||
err = acc.SetPassword(pkglog, password0)
|
||||
tcheck(t, err, "set password")
|
||||
}
|
||||
switchStop := func() {}
|
||||
@ -405,20 +408,20 @@ func TestLogin(t *testing.T) {
|
||||
tc.transactf("bad", "login too many args")
|
||||
tc.transactf("bad", "login") // no args
|
||||
tc.transactf("no", "login mjl@mox.example badpass")
|
||||
tc.transactf("no", "login mjl testtest") // must use email, not account
|
||||
tc.transactf("no", `login mjl "%s"`, password0) // must use email, not account
|
||||
tc.transactf("no", "login mjl@mox.example test")
|
||||
tc.transactf("no", "login mjl@mox.example testtesttest")
|
||||
tc.transactf("no", `login "mjl@mox.example" "testtesttest"`)
|
||||
tc.transactf("no", "login \"m\xf8x@mox.example\" \"testtesttest\"")
|
||||
tc.transactf("ok", "login mjl@mox.example testtest")
|
||||
tc.transactf("ok", `login mjl@mox.example "%s"`, password0)
|
||||
tc.close()
|
||||
|
||||
tc = start(t)
|
||||
tc.transactf("ok", `login "mjl@mox.example" "testtest"`)
|
||||
tc.transactf("ok", `login "mjl@mox.example" "%s"`, password0)
|
||||
tc.close()
|
||||
|
||||
tc = start(t)
|
||||
tc.transactf("ok", `login "\"\"@mox.example" "testtest"`)
|
||||
tc.transactf("ok", `login "\"\"@mox.example" "%s"`, password0)
|
||||
defer tc.close()
|
||||
|
||||
tc.transactf("bad", "logout badarg")
|
||||
@ -447,7 +450,7 @@ func TestState(t *testing.T) {
|
||||
}
|
||||
|
||||
// Some commands not allowed when authenticated.
|
||||
tc.transactf("ok", "login mjl@mox.example testtest")
|
||||
tc.transactf("ok", `login mjl@mox.example "%s"`, password0)
|
||||
for _, cmd := range append(append([]string{}, notAuthenticated...), selected...) {
|
||||
tc.transactf("no", "%s", cmd)
|
||||
}
|
||||
@ -472,7 +475,7 @@ func TestLiterals(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
tc.client.Create("tmpbox")
|
||||
|
||||
tc.transactf("ok", "rename {6+}\r\ntmpbox {7+}\r\nntmpbox")
|
||||
@ -495,7 +498,7 @@ func TestLiterals(t *testing.T) {
|
||||
func TestScenario(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.transactf("ok", "login mjl@mox.example testtest")
|
||||
tc.transactf("ok", `login mjl@mox.example "%s"`, password0)
|
||||
|
||||
tc.transactf("bad", " missingcommand")
|
||||
|
||||
@ -573,7 +576,7 @@ func TestScenario(t *testing.T) {
|
||||
func TestMailbox(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
|
||||
invalid := []string{
|
||||
"e\u0301", // é but as e + acute, not unicode-normalized
|
||||
@ -595,11 +598,11 @@ func TestMailbox(t *testing.T) {
|
||||
func TestMailboxDeleted(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
|
||||
tc2 := startNoSwitchboard(t)
|
||||
defer tc2.close()
|
||||
tc2.client.Login("mjl@mox.example", "testtest")
|
||||
tc2.client.Login("mjl@mox.example", password0)
|
||||
|
||||
tc.client.Create("testbox")
|
||||
tc2.client.Select("testbox")
|
||||
@ -631,7 +634,7 @@ func TestMailboxDeleted(t *testing.T) {
|
||||
func TestID(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
|
||||
tc.transactf("ok", "id nil")
|
||||
tc.xuntagged(imapclient.UntaggedID{"name": "mox", "version": moxvar.Version})
|
||||
@ -645,7 +648,7 @@ func TestID(t *testing.T) {
|
||||
func TestSequence(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
tc.client.Select("inbox")
|
||||
|
||||
tc.transactf("bad", "fetch * all") // ../rfc/9051:7018
|
||||
@ -673,13 +676,13 @@ func TestSequence(t *testing.T) {
|
||||
func DisabledTestReference(t *testing.T) {
|
||||
tc := start(t)
|
||||
defer tc.close()
|
||||
tc.client.Login("mjl@mox.example", "testtest")
|
||||
tc.client.Login("mjl@mox.example", password0)
|
||||
tc.client.Select("inbox")
|
||||
tc.client.Append("inbox", nil, nil, []byte(exampleMsg))
|
||||
|
||||
tc2 := startNoSwitchboard(t)
|
||||
defer tc2.close()
|
||||
tc2.client.Login("mjl@mox.example", "testtest")
|
||||
tc2.client.Login("mjl@mox.example", password0)
|
||||
tc2.client.Select("inbox")
|
||||
|
||||
tc.client.StoreFlagsSet("1", true, `\Deleted`)
|
||||
@ -687,7 +690,7 @@ func DisabledTestReference(t *testing.T) {
|
||||
|
||||
tc3 := startNoSwitchboard(t)
|
||||
defer tc3.close()
|
||||
tc3.client.Login("mjl@mox.example", "testtest")
|
||||
tc3.client.Login("mjl@mox.example", password0)
|
||||
tc3.transactf("ok", `list "" "inbox" return (status (messages))`)
|
||||
tc3.xuntagged(imapclient.UntaggedList{Separator: '/', Mailbox: "Inbox"}, imapclient.UntaggedStatus{Mailbox: "Inbox", Attrs: map[string]int64{"MESSAGES": 0}})
|
||||
|
||||
|
Reference in New Issue
Block a user