Fix host resolution and concurrent cache updates

This commit is contained in:
Sebastian Unterschütz committed 2026-10-27 22:23:59 +01:00
1 parent 92b1c40cb8
commit fa7446e5f7
11 files changed
+648 -113

No files matched your search

+42 -38
View File
@@ -4,7 +4,7 @@ import "strings"
// flagsWithArg lists all SSH flags that consume the following argument.
var flagsWithArg = map[byte]bool{
'b': true, 'c': true, 'D': true, 'E': true, 'e': true,
'B': true, 'P': true, 'b': true, 'c': true, 'D': true, 'E': true, 'e': true,
'F': true, 'I': true, 'i': true, 'J': true, 'L': true,
'l': true, 'm': true, 'o': true, 'O': true, 'p': true,
'Q': true, 'R': true, 'S': true, 'w': true, 'W': true,
@@ -32,18 +32,16 @@ func Parse(args []string) *ParsedArgs {
}
if strings.HasPrefix(arg, "-") && len(arg) > 1 {
flag := arg[1]
if flagsWithArg[flag] {
if len(arg) > 2 {
// argument is attached, e.g. -p2222
i++
} else {
// argument is the next element, e.g. -p 2222
i += 2
// OpenSSH accepts clusters such as -vp 2222 and -vladmin.
for j := 1; j < len(arg); j++ {
if flagsWithArg[arg[j]] {
if j == len(arg)-1 {
i++
}
break
}
} else {
i++
}
i++
continue
}
@@ -86,35 +84,41 @@ func ReplaceHost(args []string, destIdx int, newHost string) []string {
return result
}
// HasPortFlag reports whether a port was specified via -p in args.
func HasPortFlag(args []string) bool {
if parsed := Parse(args); parsed != nil {
args = args[:parsed.DestIdx]
}
for i, a := range args {
if a == "-p" && i+1 < len(args) {
return true
}
if len(a) > 2 && a[0] == '-' && a[1] == 'p' {
return true
}
}
return false
}
// HasPortFlag reports whether a port was explicitly supplied.
func HasPortFlag(args []string) bool { return hasOption(args, 'p', "Port") }
// HasUserFlag reports whether a user was specified via -l in args.
// Used to avoid overriding an explicit -l with the configured default user.
func HasUserFlag(args []string) bool {
if parsed := Parse(args); parsed != nil {
args = args[:parsed.DestIdx]
}
for i, a := range args {
if a == "-l" && i+1 < len(args) {
return true
// HasUserFlag reports whether a login user was explicitly supplied.
func HasUserFlag(args []string) bool { return hasOption(args, 'l', "User") }
func hasOption(args []string, wanted byte, keyword string) bool {
for i := 0; i < len(args); i++ {
arg := args[i]
if arg == "--" || len(arg) < 2 || arg[0] != '-' {
break
}
// handle attached form: -lroot
if len(a) > 2 && a[0] == '-' && a[1] == 'l' {
return true
for j := 1; j < len(arg); j++ {
flag := arg[j]
if !flagsWithArg[flag] {
continue
}
value := arg[j+1:]
if value == "" {
i++
if i >= len(args) {
return false
}
value = args[i]
}
if flag == wanted {
return true
}
if flag == 'o' {
fields := strings.FieldsFunc(value, func(r rune) bool { return r == '=' || r == ' ' || r == '\t' })
if len(fields) >= 2 && strings.EqualFold(fields[0], keyword) {
return true
}
}
break
}
}
return false
+46
View File
@@ -0,0 +1,46 @@
package ssh
import "testing"
func TestParseOptionClusters(t *testing.T) {
for _, args := range [][]string{
{"-vp", "2222", "server"},
{"-vp2222", "server"},
{"-vAl", "admin", "server"},
{"-vladmin", "server"},
{"-B", "eth0", "server"},
{"-P", "production", "server"},
} {
t.Run(args[0], func(t *testing.T) {
assertParsed(t, Parse(args), "server", "", len(args)-1)
})
}
}
func TestExplicitSSHOptions(t *testing.T) {
for _, tc := range []struct {
name string
args []string
user, port bool
}{
{"cluster port separated", []string{"-vp", "2222", "server"}, false, true},
{"cluster user attached", []string{"-vladmin", "server"}, true, false},
{"o separated", []string{"-o", "User=admin", "-o", "Port=2222", "server"}, true, true},
{"o attached and case insensitive", []string{"-ouSeR=admin", "-oport=2222", "server"}, true, true},
{"o whitespace", []string{"-o", " User = admin", "-o", "Port\t2222", "server"}, true, true},
{"cluster o", []string{"-voUser=admin", "server"}, true, false},
{"option value looks like flag", []string{"-i", "-lroot", "-F", "-p2222", "server"}, false, false},
{"remote flags", []string{"server", "-p2222", "-o", "User=admin"}, false, false},
{"after double dash", []string{"--", "-lroot", "-p2222"}, false, false},
{"missing value", []string{"-vp"}, false, false},
} {
t.Run(tc.name, func(t *testing.T) {
if got := HasUserFlag(tc.args); got != tc.user {
t.Errorf("HasUserFlag(%v) = %v, want %v", tc.args, got, tc.user)
}
if got := HasPortFlag(tc.args); got != tc.port {
t.Errorf("HasPortFlag(%v) = %v, want %v", tc.args, got, tc.port)
}
})
}
}