fix: 统一对话密码锁键为发送方加对方不含 IP
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -297,6 +298,107 @@ func TestSelfLoginPasswordAndLogout(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestU03TalkPairLockIgnoresIPAndEmptyPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
app, db, locks := openIdentity(t)
|
||||
ctx := context.Background()
|
||||
insertEP(t, db, "alice", "password1")
|
||||
insertEP(t, db, "bob", "password1")
|
||||
if err := app.SelfSetTalkPassword(ctx, "bob", "secret"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 9; i++ {
|
||||
err := app.UnlockTalk(ctx, "alice", "bob", "wrong", fmt.Sprintf("10.0.0.%d", i+1))
|
||||
if protoCode(err) != protocol.CodeTalkPasswordInvalid {
|
||||
t.Fatalf("fail %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "secret", "9.9.9.9"); err != nil {
|
||||
t.Fatalf("9th+correct from other IP should succeed: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "wrong", fmt.Sprintf("1.1.1.%d", i+1)); protoCode(err) != protocol.CodeTalkPasswordInvalid {
|
||||
t.Fatalf("unlock fail %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := app.CheckTalkPasswordForJoin(ctx, "alice", "bob", "wrong", fmt.Sprintf("2.2.2.%d", i+1)); protoCode(err) != protocol.CodeTalkPasswordInvalid {
|
||||
t.Fatalf("join fail %d: %v", i, err)
|
||||
}
|
||||
}
|
||||
pair := auth.LockKey{Kind: auth.LockTalkPair, EndpointID: "alice", PeerID: "bob"}
|
||||
if locked, _ := locks.Check(pair); !locked {
|
||||
t.Fatal("pair should lock after 10 wrong attempts across IPs and paths")
|
||||
}
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "secret", "8.8.8.8"); protoCode(err) != protocol.CodeRateLimited {
|
||||
t.Fatalf("want rate_limited unlock got %v", err)
|
||||
}
|
||||
if err := app.CheckTalkPasswordForJoin(ctx, "alice", "bob", "secret", "7.7.7.7"); protoCode(err) != protocol.CodeRateLimited {
|
||||
t.Fatalf("want rate_limited join got %v", err)
|
||||
}
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "", "6.6.6.6"); protoCode(err) != protocol.CodeTalkPasswordRequired {
|
||||
t.Fatalf("empty while locked want required got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestU03AdminChangeAndDeleteClearTalkLocks(t *testing.T) {
|
||||
t.Parallel()
|
||||
app, db, locks := openIdentity(t)
|
||||
ctx := context.Background()
|
||||
insertEP(t, db, "alice", "password1")
|
||||
insertEP(t, db, "bob", "password1")
|
||||
if err := app.SelfSetTalkPassword(ctx, "bob", "secret"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < 50; i++ {
|
||||
id := fmt.Sprintf("u%02d", i)
|
||||
insertEP(t, db, id, "password1")
|
||||
_ = app.UnlockTalk(ctx, id, "bob", "wrong", "2.2.2.2")
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockTalkTarget, EndpointID: "bob"}); !locked {
|
||||
t.Fatal("expected talk target lock")
|
||||
}
|
||||
if err := app.SelfSetTalkPassword(ctx, "bob", "secret2"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockTalkTarget, EndpointID: "bob"}); locked {
|
||||
t.Fatal("admin/self change should clear LockTalkTarget")
|
||||
}
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "secret2", "3.3.3.3"); err != nil {
|
||||
t.Fatalf("unlock after change: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
_ = app.UnlockTalk(ctx, "alice", "bob", "wrong", fmt.Sprintf("4.4.4.%d", i+1))
|
||||
}
|
||||
locks.Fail(auth.LockKey{Kind: auth.LockLoginEndpoint, EndpointID: "bob"})
|
||||
locks.Fail(auth.LockKey{Kind: auth.LockTalkPair, EndpointID: "bob", PeerID: "alice"})
|
||||
if err := app.Delete(ctx, "bob"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockTalkPair, EndpointID: "alice", PeerID: "bob"}); locked {
|
||||
t.Fatal("delete should clear pair where bob is peer")
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockTalkPair, EndpointID: "bob", PeerID: "alice"}); locked {
|
||||
t.Fatal("delete should clear pair where bob is sender")
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockTalkTarget, EndpointID: "bob"}); locked {
|
||||
t.Fatal("delete should clear LockTalkTarget")
|
||||
}
|
||||
if locked, _ := locks.Check(auth.LockKey{Kind: auth.LockLoginEndpoint, EndpointID: "bob"}); locked {
|
||||
t.Fatal("delete should clear login lock")
|
||||
}
|
||||
insertEP(t, db, "bob", "password1")
|
||||
if err := app.SelfSetTalkPassword(ctx, "bob", "secret"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := app.UnlockTalk(ctx, "alice", "bob", "secret", "5.5.5.5"); err != nil {
|
||||
t.Fatalf("reopened bob must not inherit talk lock: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnlockSelfAndNoPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
app, db, _ := openIdentity(t)
|
||||
|
||||
Reference in New Issue
Block a user