check / check (push) Successful in 2m4s
The README now gives the child mnemonic keyfunc prints for the abandon ... about test mnemonic at index 0, checked by the README vectors test; the BIP-85 specification vector stays, marked as starting from a master key keyfunc cannot take. It also says ssh install needs the host key in known_hosts already, and how to get round that. ssh install now also lists ~/.ssh/. on its first connection and refuses, before any upload, a ~/.ssh it can read but not enter, which sftp shows as empty; a file where ~/.ssh belongs is refused the same way. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
142 lines
4.2 KiB
Go
142 lines
4.2 KiB
Go
//nolint:testpackage // absent is what these wordings are read by
|
|
package ssh
|
|
|
|
import "testing"
|
|
|
|
// What a session says besides its report on the file that was asked
|
|
// for: sftp echoes the command it is running, and ssh warns about an
|
|
// identity file it cannot find in the words of a missing file even
|
|
// though the session goes on to authenticate.
|
|
const (
|
|
echoed = `sftp> get .ssh/authorized_keys "/tmp/keyfunc/authorized_keys"
|
|
`
|
|
listed = "sftp> ls -1 .ssh\n"
|
|
warning = `Warning: Identity file /gone not accessible: ` +
|
|
"No such file or directory.\n"
|
|
)
|
|
|
|
// TestAbsenceIsReadOnlyFromWhatSFTPSaidAboutAuthorizedKeys holds the
|
|
// wordings the OpenSSH client was seen to use against a real server:
|
|
// a file it cannot find is reported one way, naming the path the
|
|
// server expanded, and everything else it says is a failure.
|
|
func TestAbsenceIsReadOnlyFromWhatSFTPSaidAboutAuthorizedKeys(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
sessions := map[string]struct {
|
|
said string
|
|
want bool
|
|
}{
|
|
"the file is not there": {
|
|
said: echoed +
|
|
`File "/home/someone/.ssh/authorized_keys" not found.` + "\n",
|
|
want: true,
|
|
},
|
|
"the file is not there, named as it was asked for": {
|
|
said: echoed + `File ".ssh/authorized_keys" not found.` + "\n",
|
|
want: true,
|
|
},
|
|
"the file is not there and an identity file is not either": {
|
|
said: warning + echoed +
|
|
`File "/home/someone/.ssh/authorized_keys" not found.` + "\n",
|
|
want: true,
|
|
},
|
|
"the file is there and cannot be read": {
|
|
said: echoed +
|
|
`remote open "/home/someone/.ssh/authorized_keys": ` +
|
|
"Permission denied\n",
|
|
want: false,
|
|
},
|
|
"only an identity file is not there": {
|
|
said: warning + echoed +
|
|
`remote open "/home/someone/.ssh/authorized_keys": ` +
|
|
"Permission denied\n",
|
|
want: false,
|
|
},
|
|
"some other file is not there": {
|
|
said: echoed + `File "/home/someone/.ssh/known_hosts" not found.` +
|
|
"\n",
|
|
want: false,
|
|
},
|
|
"the connection did not come up": {
|
|
said: "ssh: connect to host example.com port 22: " +
|
|
"Connection refused\nConnection closed\n",
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for name, session := range sessions {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if absent(session.said) != session.want {
|
|
t.Errorf(
|
|
"read as absent: %t, wanted %t, from:\n%s",
|
|
!session.want, session.want, session.said,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestTheDirectoryIsReadAsAbsentOnlyFromTheListingSayingSo holds the
|
|
// wordings the OpenSSH client was seen to use when a listing fails: a
|
|
// directory it cannot find is reported one way, and one it cannot read
|
|
// another, and only the first is read as a host with no .ssh yet. A
|
|
// .ssh that can be read but not entered lists as empty, and the
|
|
// listing of .ssh/. that follows reports that path, not .ssh, as not
|
|
// found.
|
|
func TestTheDirectoryIsReadAsAbsentOnlyFromTheListingSayingSo(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
listings := map[string]struct {
|
|
said string
|
|
want bool
|
|
}{
|
|
"the directory is not there": {
|
|
said: listed + `Can't ls: "/home/someone/.ssh" not found` + "\n",
|
|
want: true,
|
|
},
|
|
"the directory is not there, named as it was asked for": {
|
|
said: listed + `Can't ls: ".ssh" not found` + "\n",
|
|
want: true,
|
|
},
|
|
"the directory is not there and an identity file is not either": {
|
|
said: warning + listed +
|
|
`Can't ls: "/home/someone/.ssh" not found` + "\n",
|
|
want: true,
|
|
},
|
|
"the directory is there and cannot be read": {
|
|
said: listed +
|
|
`remote readdir("/home/someone/.ssh/"): Permission denied` + "\n",
|
|
want: false,
|
|
},
|
|
"the directory is there and cannot be entered": {
|
|
said: listed + "sftp> ls -1 .ssh/.\n" +
|
|
`Can't ls: "/home/someone/.ssh/." not found` + "\n",
|
|
want: false,
|
|
},
|
|
"some other directory is not there": {
|
|
said: listed + `Can't ls: "/home/someone/.config" not found` + "\n",
|
|
want: false,
|
|
},
|
|
"the connection did not come up": {
|
|
said: "ssh: connect to host example.com port 22: " +
|
|
"Connection refused\nConnection closed\n",
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for name, listing := range listings {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if listingNotFound(listing.said, directory) != listing.want {
|
|
t.Errorf(
|
|
"read as absent: %t, wanted %t, from:\n%s",
|
|
!listing.want, listing.want, listing.said,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|