1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2025-12-19 14:57:04 +00:00

userdb: Add support for receive-only users

Some use cases, like receive-only MTAs, need domain users for receiving
emails, but have no real need for passwords since they will never use
submission.

Today, that is not supported, and those use-cases require the
administrator to come up with a password unnecessarily, adding
complexity and possibly risk.

This patch implements "receive-only users", which don't have a valid
password, thus exist for the purposes of delivering mail, but always
fail authentication.

See https://github.com/albertito/chasquid/issues/44 for more details and
rationale.

Thanks to xavierg who suggested this feature on IRC.
This commit is contained in:
Alberto Bertogli
2023-12-03 00:12:46 +00:00
parent dbff2f0455
commit 83ae4c3478
9 changed files with 213 additions and 47 deletions

View File

@@ -122,24 +122,27 @@ func TestWrite(t *testing.T) {
t.Fatalf("expected %v, got %v", emptyDB, db)
}
// Add two users, write, and load again.
// Add users, write, and load again.
if err := db.AddUser("user1", "passwd1"); err != nil {
t.Fatalf("failed to add user1: %v", err)
}
if err := db.AddUser("ñoño", "añicos"); err != nil {
t.Fatalf("failed to add ñoño: %v", err)
}
if err := db.AddDeniedUser("ñaca"); err != nil {
t.Fatalf("failed to add ñaca: %v", err)
}
if err := db.Write(); err != nil {
t.Fatalf("error writing database: %v", err)
}
db = mustLoad(t, fname)
for _, name := range []string{"user1", "ñoño"} {
for _, name := range []string{"user1", "ñoño", "ñaca"} {
if !db.Exists(name) {
t.Errorf("user %q not in database", name)
}
if db.db.Users[name].GetScheme() == nil {
t.Errorf("user %q not using scrypt: %#v", name, db.db.Users[name])
t.Errorf("user %q missing scheme: %#v", name, db.db.Users[name])
}
}
@@ -153,6 +156,8 @@ func TestWrite(t *testing.T) {
{"user1", "passwd12", false},
{"ñoño", "añicos", true},
{"ñoño", "anicos", false},
{"ñaca", "", false},
{"ñaca", "lalala", false},
{"notindb", "something", false},
{"", "", false},
{" ", " ", false},
@@ -202,6 +207,11 @@ func TestInvalidUsername(t *testing.T) {
if err == nil {
t.Errorf("AddUser(%q) worked, expected it to fail", name)
}
err = db.AddDeniedUser(name)
if err == nil {
t.Errorf("AddDeniedUser(%q) worked, expected it to fail", name)
}
}
}
@@ -235,6 +245,24 @@ func TestPlainScheme(t *testing.T) {
}
}
// Test the denied scheme.
func TestDeniedScheme(t *testing.T) {
fname := mustCreateDB(t, "")
defer removeIfSuccessful(t, fname)
db := mustLoad(t, fname)
db.db.Users["user"] = &Password{Scheme: &Password_Denied{}}
err := db.Write()
if err != nil {
t.Errorf("Write failed: %v", err)
}
db = mustLoad(t, fname)
if db.Authenticate("user", "anything") {
t.Errorf("denied authentication worked but it shouldn't")
}
}
func TestReload(t *testing.T) {
content := "users:< key: 'u1' value:< plain:< password: 'pass' >>>"
fname := mustCreateDB(t, content)
@@ -326,4 +354,12 @@ func TestExists(t *testing.T) {
if !db.Exists("user") {
t.Errorf("known user does not exist")
}
if err := db.AddDeniedUser("denieduser"); err != nil {
t.Fatalf("error adding user: %v", err)
}
if !db.Exists("denieduser") {
t.Errorf("known (denied) user does not exist")
}
}