Read an account by its name, never as a number getent takes for a uid (hq ADR 0325)
mesh/merge-gate head 5c8e768ef520 merged into trunk ef26dba2753a — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
mesh/repo-check head 5c8e768ef520 merged into trunk ef26dba2753a — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/merge-gate head 5c8e768ef520 merged into trunk ef26dba2753a — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
mesh/repo-check head 5c8e768ef520 merged into trunk ef26dba2753a — pass: its merge-check.sh passed
mesh/delivery delivered
getent passwd reads an all-digit key as a uid, so a tool runner's account named "1000" resolved to whoever has uid 1000 and the entry went to them. Only an answer naming the account asked for is taken.
This commit is contained in:
@@ -301,6 +301,12 @@ func (e Exec) IDs(ctx context.Context, account string) (uid, gid int, found bool
|
||||
return 0, 0, false, fmt.Errorf("the user database gave %q for %q, which is not a passwd entry",
|
||||
strings.TrimSpace(out), account)
|
||||
}
|
||||
// getent reads an all-digit key as a uid: "1000" answers with whoever has uid 1000. Only the account named is
|
||||
// the one asked for.
|
||||
if fields[0] != account {
|
||||
return 0, 0, false, fmt.Errorf("the user database answered %q with the account %q: an account is named, "+
|
||||
"never numbered", account, fields[0])
|
||||
}
|
||||
uid, uerr := strconv.Atoi(fields[2])
|
||||
gid, gerr := strconv.Atoi(fields[3])
|
||||
if uerr != nil || gerr != nil {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// An account is read by its name (novox/hq ADR 0325 §4): getent reads an all-digit key as a uid, so "1000" would
|
||||
// answer with whoever has uid 1000 — refused, never taken for the account named.
|
||||
func TestAnAccountIsReadByItsNameNeverItsNumber(t *testing.T) {
|
||||
db := map[string]string{
|
||||
"nox": "nox:x:1003:1003::/home/nox:/bin/sh",
|
||||
"1000": "jochen:x:1000:1000::/home/jochen:/bin/zsh", // what getent answers for a uid
|
||||
}
|
||||
e := Exec{Run: func(_ context.Context, name string, args ...string) (string, error) {
|
||||
if line, ok := db[args[len(args)-1]]; ok {
|
||||
return line + "\n", nil
|
||||
}
|
||||
return "", errors.New("getent exited 2")
|
||||
}}
|
||||
if uid, gid, found, err := e.IDs(context.Background(), "nox"); err != nil || !found || uid != 1003 || gid != 1003 {
|
||||
t.Fatalf("nox: %d %d %v %v", uid, gid, found, err)
|
||||
}
|
||||
if _, _, found, err := e.IDs(context.Background(), "1000"); found || err == nil || !strings.Contains(err.Error(), "jochen") {
|
||||
t.Fatalf("an all-digit name was read as a uid: found=%v err=%v", found, err)
|
||||
}
|
||||
if _, _, found, err := e.IDs(context.Background(), "ghost"); found || err != nil {
|
||||
t.Fatalf("an absent account: found=%v err=%v", found, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user