Review 1 of S1: list's served text ends with the account sentence only; a secret-shaped link target in a secret place is withheld
Issue 1409. readTools no longer appends the refusal sentence to list. A row in TestSecretPlacesAreRefusedByNameBeforeAnyRead holds a link's target in a secret place to the content rule. S2's match on sudo's English message is left as it is: the root path sets no locale, and sudo's environment handling decides whether LC_ALL reaches stat. Builds: design 39 parts D3 (§15), bullets 2 and 4
This commit is contained in:
@@ -171,7 +171,9 @@ func object(props map[string]any, required ...string) map[string]any {
|
||||
|
||||
// The descriptions of the reads are the controller's (internal/catalogue/files.go): the reads' own, with
|
||||
// where they are read as restated for the operator's account.
|
||||
const asAccount = "as the node's operator account, through sudo -n where its rights do not reach; a place a " +
|
||||
const readsAs = "as the node's operator account, through sudo -n where its rights do not reach"
|
||||
|
||||
const asAccount = readsAs + "; a place a " +
|
||||
"secret is kept, or a known credential file, is refused by name"
|
||||
|
||||
func boolArg(a map[string]any, k string) bool { return arg(a, k) == "true" }
|
||||
@@ -266,7 +268,7 @@ func tools(f *Files) []stdio.Tool {
|
||||
func readTools(r Reader) []stdio.Tool {
|
||||
ts := rawReadTools(r)
|
||||
for i := range ts {
|
||||
if !strings.Contains(ts[i].Description, asAccount) {
|
||||
if !strings.Contains(ts[i].Description, readsAs) {
|
||||
ts[i].Description += " Read " + asAccount + "."
|
||||
}
|
||||
}
|
||||
@@ -288,7 +290,7 @@ func rawReadTools(r Reader) []stdio.Tool {
|
||||
verb("list", "Every entry of one directory with its type, owner, group, mode, size and, for a link, its "+
|
||||
"target. At most 2000 entries; a longer directory is cut and says so. A place a secret is kept is "+
|
||||
"listed too, at any depth, and marked secret-place: its entries, never their content; what reaches a "+
|
||||
"process's memory or files (/proc/<pid>/environ, mem, fd, map_files, root, cwd) is refused by name.",
|
||||
"process's memory or files (/proc/<pid>/environ, mem, fd, map_files, root, cwd) is refused by name. Read "+readsAs+".",
|
||||
object(map[string]any{"path": str("an absolute path to a directory")}, "path"),
|
||||
func(a map[string]any) (any, error) { return r.List(arg(a, "path")) }),
|
||||
verb("read", "One text file, or a part of it by line: at most 256 KiB in one answer (64 KiB unless more "+
|
||||
|
||||
@@ -95,6 +95,21 @@ func TestSecretPlacesAreRefusedByNameBeforeAnyRead(t *testing.T) {
|
||||
if a, err := r.List(filepath.Join(dir, "home/ops")); err != nil || a.Secret != "" {
|
||||
t.Errorf("a plain directory is marked: %+v %v", a, err)
|
||||
}
|
||||
// a link in a secret place: the entry is answered, its target held to the content rule (ADR 0394 §8)
|
||||
if err := os.Symlink(aToken, filepath.Join(vault, "ledger/tokenlink")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a, err := r.List(filepath.Join(vault, "ledger")); err != nil || a.Secret == "" || len(a.Withheld) != 1 ||
|
||||
a.Withheld[0].At != "a link's target" || strings.Contains(a.Entries[0].Link+a.Entries[1].Link, aToken) {
|
||||
t.Errorf("a secret-shaped target in a secret place: %+v %v", a, err)
|
||||
}
|
||||
// the served text of list says it lists a secret place, and no longer that it refuses one
|
||||
for _, tl := range readTools(r) {
|
||||
if tl.Name == "list" && (strings.Contains(tl.Description, "known credential file, is refused") ||
|
||||
!strings.HasSuffix(tl.Description, "where its rights do not reach.")) {
|
||||
t.Errorf("the list text: %s", tl.Description)
|
||||
}
|
||||
}
|
||||
if _, err := r.List("/proc/self/fd"); err == nil || !strings.Contains(err.Error(), "refused by name") {
|
||||
t.Errorf("a process's open files were listed: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user