From 9fcf5f502961256fae928eccb0bc6fcb8a606fa0 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Mon, 7 Aug 2023 23:09:37 +0700 Subject: ssh/config: handle key UserKnownHostsFile The UserKnownHostsFile define list of the known_hosts files to be read, separated by spaces. If not set default to "~/.ssh/known_hosts" and "~/.ssh/known_hosts2". --- lib/ssh/config/section.go | 45 +++++++++++++++++++++++++++++++++++------- lib/ssh/config/section_test.go | 31 +++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 7 deletions(-) (limited to 'lib/ssh') diff --git a/lib/ssh/config/section.go b/lib/ssh/config/section.go index c324aee5..7d81a2d2 100644 --- a/lib/ssh/config/section.go +++ b/lib/ssh/config/section.go @@ -33,6 +33,7 @@ const ( KeyCertificateFile = `certificatefile` KeyIdentityFile = `identityfile` KeySendEnv = `sendenv` + KeyUserKnownHostsFile = `userknownhostsfile` // List of key in Host or Match with integer value. KeyCanonicalizeMaxDots = `canonicalizemaxdots` @@ -120,17 +121,19 @@ const ( keyTunnelDevince = "tunneldevice" keyUpdatehostKeys = "updatehostkeys" keyUseKeychain = "usekeychain" - keyUserKnownHostsFile = "userknownhostsfile" keyVerifyHostKeyDNS = "verifyhostkeydns" ) -// Valid values for key AddKeysToAgent. +// Known values for key. const ( - ValueAlways = `always` - ValueAsk = `ask` - ValueConfirm = `confirm` - ValueNo = `no` - ValueYes = `yes` + ValueAcceptNew = `accept-new` + ValueAlways = `always` + ValueAsk = `ask` + ValueConfirm = `confirm` + ValueOff = `off` + ValueNo = `no` + ValueNone = `none` + ValueYes = `yes` ) // Valid values for key AddressFamily. @@ -169,6 +172,14 @@ func defaultIdentityFile() []string { } } +// defaultUserKnownHostsFile return list of default KnownHostsFile. +func defaultUserKnownHostsFile() []string { + return []string{ + `~/.ssh/known_hosts`, + `~/.ssh/known_hosts2`, + } +} + // Section is the type that represent SSH client Host and Match section in // configuration. type Section struct { @@ -202,6 +213,7 @@ type Section struct { certificateFile []string IdentityFile []string + knownHostsFile []string sendEnv []string // Patterns for Host section. @@ -542,6 +554,9 @@ func (section *Section) Set(key, value string) (err error) { section.setEnv(value) case KeyUser: // User name is case sensitive. + case KeyUserKnownHostsFile: + section.setUserKnownHostsFile(value) + case KeyVisualHostKey: _, err = parseBool(key, value) case KeyXAuthLocation: @@ -560,6 +575,15 @@ func (section *Section) User() string { return section.Field[KeyUser] } +// UserKnownHostsFile return list of user known_hosts file set in this +// Section. +func (section *Section) UserKnownHostsFile() []string { + if len(section.knownHostsFile) == 0 { + return defaultUserKnownHostsFile() + } + return section.knownHostsFile +} + // setEnv set the Environments with key and value of format "KEY=VALUE". func (section *Section) setEnv(env string) { kv := strings.SplitN(env, "=", 2) @@ -568,6 +592,13 @@ func (section *Section) setEnv(env string) { } } +func (section *Section) setUserKnownHostsFile(val string) { + var list = strings.Fields(val) + if len(list) > 0 { + section.knownHostsFile = append(section.knownHostsFile, list...) + } +} + func validateAddKeysToAgent(val string) (err error) { switch val { case ValueAlways, ValueAsk, ValueConfirm, ValueNo, ValueYes: diff --git a/lib/ssh/config/section_test.go b/lib/ssh/config/section_test.go index 7f812f6c..72c02af6 100644 --- a/lib/ssh/config/section_test.go +++ b/lib/ssh/config/section_test.go @@ -149,3 +149,34 @@ func TestSection_Environments(t *testing.T) { test.Assert(t, c.pattern, c.exp, got) } } + +func TestSection_UserKnownHostsFile(t *testing.T) { + type testCase struct { + value string + exp []string + } + + var listCase = []testCase{{ + exp: defaultUserKnownHostsFile(), + }, { + value: `~/.ssh/myhost ~/.ssh/myhost2`, + exp: []string{ + `~/.ssh/myhost`, + `~/.ssh/myhost2`, + }, + }} + + var ( + section = newSection(`test`) + + c testCase + err error + ) + for _, c = range listCase { + err = section.Set(KeyUserKnownHostsFile, c.value) + if err != nil { + t.Fatal(err) + } + test.Assert(t, c.value, c.exp, section.UserKnownHostsFile()) + } +} -- cgit v1.3