mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-02-08 00:21:23 +01:00
merge branch 'main' into sylvie/ssh-agent
This commit is contained in:
commit
0d10632c62
14
go.work.sum
14
go.work.sum
@ -134,14 +134,28 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
|
||||
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
|
||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
|
@ -20,9 +20,9 @@ require (
|
||||
github.com/sashabaranov/go-openai v1.9.0
|
||||
github.com/sawka/txwrap v0.1.2
|
||||
github.com/wavetermdev/waveterm/waveshell v0.0.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/mod v0.10.0
|
||||
golang.org/x/sys v0.15.0
|
||||
golang.org/x/sys v0.21.0
|
||||
mvdan.cc/sh/v3 v3.7.0
|
||||
)
|
||||
|
||||
@ -30,6 +30,7 @@ require (
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
)
|
||||
|
||||
|
@ -53,6 +53,8 @@ github.com/sashabaranov/go-openai v1.9.0 h1:NoiO++IISxxJ1pRc0n7uZvMGMake0G+FJ1XP
|
||||
github.com/sashabaranov/go-openai v1.9.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||
github.com/sawka/txwrap v0.1.2 h1:v8xS0Z1LE7/6vMZA81PYihI+0TSR6Zm1MalzzBIuXKc=
|
||||
github.com/sawka/txwrap v0.1.2/go.mod h1:T3nlw2gVpuolo6/XEetvBbk1oMXnY978YmBFy1UyHvw=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
@ -63,11 +65,15 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/kevinburke/ssh_config"
|
||||
"github.com/skeema/knownhosts"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbus"
|
||||
@ -29,13 +30,15 @@ import (
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/userinput"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
"golang.org/x/crypto/ssh/knownhosts"
|
||||
xknownhosts "golang.org/x/crypto/ssh/knownhosts"
|
||||
)
|
||||
|
||||
type UserInputCancelError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
type HostKeyAlgorithms = func(hostWithPort string) (algos []string)
|
||||
|
||||
func (uice UserInputCancelError) Error() string {
|
||||
return uice.Err.Error()
|
||||
}
|
||||
@ -407,7 +410,7 @@ func lineContainsMatch(line []byte, matches [][]byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, HostKeyAlgorithms, error) {
|
||||
ssh_config.ReloadConfigs()
|
||||
rawUserKnownHostsFiles, _ := ssh_config.GetStrict(opts.SSHHost, "UserKnownHostsFile")
|
||||
userKnownHostsFiles := strings.Fields(rawUserKnownHostsFiles) // TODO - smarter splitting escaped spaces and quotes
|
||||
@ -416,7 +419,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
|
||||
osUser, err := user.Current()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
var unexpandedKnownHostsFiles []string
|
||||
if osUser.Username == "root" {
|
||||
@ -432,7 +435,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
|
||||
// there are no good known hosts files
|
||||
if len(knownHostsFiles) == 0 {
|
||||
return nil, fmt.Errorf("no known_hosts files provided by ssh. defaults are overridden")
|
||||
return nil, nil, fmt.Errorf("no known_hosts files provided by ssh. defaults are overridden")
|
||||
}
|
||||
|
||||
var unreadableFiles []string
|
||||
@ -441,9 +444,10 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
// incorrectly. if a problem file is found, it is removed from our list
|
||||
// and we try again
|
||||
var basicCallback ssh.HostKeyCallback
|
||||
var hostKeyAlgorithms HostKeyAlgorithms
|
||||
for basicCallback == nil && len(knownHostsFiles) > 0 {
|
||||
var err error
|
||||
basicCallback, err = knownhosts.New(knownHostsFiles...)
|
||||
keyDb, err := knownhosts.NewDB(knownHostsFiles...)
|
||||
if serr, ok := err.(*os.PathError); ok {
|
||||
badFile := serr.Path
|
||||
unreadableFiles = append(unreadableFiles, badFile)
|
||||
@ -454,18 +458,26 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
}
|
||||
}
|
||||
if len(okFiles) >= len(knownHostsFiles) {
|
||||
return nil, fmt.Errorf("problem file (%s) doesn't exist. this should not be possible", badFile)
|
||||
return nil, nil, fmt.Errorf("problem file (%s) doesn't exist. this should not be possible", badFile)
|
||||
}
|
||||
knownHostsFiles = okFiles
|
||||
} else if err != nil {
|
||||
// TODO handle obscure problems if possible
|
||||
return nil, fmt.Errorf("known_hosts formatting error: %+v", err)
|
||||
return nil, nil, fmt.Errorf("known_hosts formatting error: %+v", err)
|
||||
} else {
|
||||
basicCallback = keyDb.HostKeyCallback()
|
||||
hostKeyAlgorithms = keyDb.HostKeyAlgorithms
|
||||
}
|
||||
}
|
||||
|
||||
if basicCallback == nil {
|
||||
basicCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return &knownhosts.KeyError{}
|
||||
return &xknownhosts.KeyError{}
|
||||
}
|
||||
// need to return nil here to avoid null pointer from attempting to call
|
||||
// the one provided by the db if nothing was found
|
||||
hostKeyAlgorithms = func(hostWithPort string) (algos []string) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,21 +486,21 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
if err == nil {
|
||||
// success
|
||||
return nil
|
||||
} else if _, ok := err.(*knownhosts.RevokedError); ok {
|
||||
} else if _, ok := err.(*xknownhosts.RevokedError); ok {
|
||||
// revoked credentials are refused outright
|
||||
return err
|
||||
} else if _, ok := err.(*knownhosts.KeyError); !ok {
|
||||
} else if _, ok := err.(*xknownhosts.KeyError); !ok {
|
||||
// this is an unknown error (note the !ok is opposite of usual)
|
||||
return err
|
||||
}
|
||||
serr, _ := err.(*knownhosts.KeyError)
|
||||
serr, _ := err.(*xknownhosts.KeyError)
|
||||
if len(serr.Want) == 0 {
|
||||
// the key was not found
|
||||
|
||||
// try to write to a file that could be read
|
||||
err := fmt.Errorf("placeholder, should not be returned") // a null value here can cause problems with empty slice
|
||||
for _, filename := range knownHostsFiles {
|
||||
newLine := knownhosts.Line([]string{knownhosts.Normalize(hostname)}, key)
|
||||
newLine := xknownhosts.Line([]string{xknownhosts.Normalize(hostname)}, key)
|
||||
getUserVerification := createUnknownKeyVerifier(filename, hostname, remote.String(), key)
|
||||
err = writeToKnownHosts(filename, newLine, getUserVerification)
|
||||
if err == nil {
|
||||
@ -503,7 +515,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
// should catch cases where there is no known_hosts file
|
||||
if err != nil {
|
||||
for _, filename := range unreadableFiles {
|
||||
newLine := knownhosts.Line([]string{knownhosts.Normalize(hostname)}, key)
|
||||
newLine := xknownhosts.Line([]string{xknownhosts.Normalize(hostname)}, key)
|
||||
getUserVerification := createMissingKnownHostsVerifier(filename, hostname, remote.String(), key)
|
||||
err = writeToKnownHosts(filename, newLine, getUserVerification)
|
||||
if err == nil {
|
||||
@ -553,7 +565,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
return fmt.Errorf("remote host identification has changed")
|
||||
}
|
||||
|
||||
updatedCallback, err := knownhosts.New(knownHostsFiles...)
|
||||
updatedCallback, err := xknownhosts.New(knownHostsFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -561,7 +573,7 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
return updatedCallback(hostname, remote, key)
|
||||
}
|
||||
|
||||
return waveHostKeyCallback, nil
|
||||
return waveHostKeyCallback, hostKeyAlgorithms, nil
|
||||
}
|
||||
|
||||
func DialContext(ctx context.Context, network string, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
@ -637,17 +649,18 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
|
||||
authMethods = append(authMethods, authMethod)
|
||||
}
|
||||
|
||||
hostKeyCallback, err := createHostKeyCallback(opts)
|
||||
hostKeyCallback, hostKeyAlgorithms, err := createHostKeyCallback(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
networkAddr := sshKeywords.HostName + ":" + sshKeywords.Port
|
||||
clientConfig := &ssh.ClientConfig{
|
||||
User: sshKeywords.User,
|
||||
Auth: authMethods,
|
||||
HostKeyCallback: hostKeyCallback,
|
||||
HostKeyAlgorithms: hostKeyAlgorithms(networkAddr),
|
||||
}
|
||||
networkAddr := sshKeywords.HostName + ":" + sshKeywords.Port
|
||||
return DialContext(connCtx, "tcp", networkAddr, clientConfig)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user