Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6d4a5c6

Browse filesBrowse files
authored
Merge pull request #1515 from pjbgf/regre
plumbing: transport, Reintroduce SetHostKeyCallback. Fix #1514
2 parents 763ce2e + beedd6b commit 6d4a5c6
Copy full SHA for 6d4a5c6

File tree

2 files changed

+132
-1
lines changed
Filter options

2 files changed

+132
-1
lines changed

‎plumbing/transport/ssh/auth_method.go

Copy file name to clipboardExpand all lines: plumbing/transport/ssh/auth_method.go
+31-1Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,10 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
231231
// /etc/ssh/ssh_known_hosts
232232
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
233233
kh, err := NewKnownHostsDb(files...)
234-
return kh.HostKeyCallback(), err
234+
if err != nil {
235+
return nil, err
236+
}
237+
return kh.HostKeyCallback(), nil
235238
}
236239

237240
// NewKnownHostsDb returns knownhosts.HostKeyDB based on a file based on a
@@ -311,13 +314,40 @@ type HostKeyCallbackHelper struct {
311314
// HostKeyAlgorithms is a list of supported host key algorithms that will
312315
// be used for host key verification.
313316
HostKeyAlgorithms []string
317+
318+
// fallback allows for injecting the fallback call, which is called
319+
// when a HostKeyCallback is not set.
320+
fallback func(files ...string) (ssh.HostKeyCallback, error)
314321
}
315322

316323
// SetHostKeyCallbackAndAlgorithms sets the field HostKeyCallback and HostKeyAlgorithms in the given cfg.
317324
// If the host key callback or algorithms is empty it is left empty. It will be handled by the dial method,
318325
// falling back to knownhosts.
319326
func (m *HostKeyCallbackHelper) SetHostKeyCallbackAndAlgorithms(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
327+
if cfg == nil {
328+
cfg = &ssh.ClientConfig{}
329+
}
330+
331+
if m.HostKeyCallback == nil {
332+
if m.fallback == nil {
333+
m.fallback = NewKnownHostsCallback
334+
}
335+
336+
hkcb, err := m.fallback()
337+
if err != nil {
338+
return nil, fmt.Errorf("cannot create known hosts callback: %w", err)
339+
}
340+
341+
cfg.HostKeyCallback = hkcb
342+
cfg.HostKeyAlgorithms = m.HostKeyAlgorithms
343+
return cfg, err
344+
}
345+
320346
cfg.HostKeyCallback = m.HostKeyCallback
321347
cfg.HostKeyAlgorithms = m.HostKeyAlgorithms
322348
return cfg, nil
323349
}
350+
351+
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
352+
return m.SetHostKeyCallbackAndAlgorithms(cfg)
353+
}

‎plumbing/transport/ssh/auth_method_test.go

Copy file name to clipboardExpand all lines: plumbing/transport/ssh/auth_method_test.go
+101Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ import (
44
"bufio"
55
"fmt"
66
"os"
7+
"reflect"
78
"runtime"
89
"slices"
910
"strings"
11+
"testing"
1012

1113
"github.com/go-git/go-billy/v5/osfs"
1214
"github.com/go-git/go-billy/v5/util"
15+
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
1317
"golang.org/x/crypto/ssh"
1418
"golang.org/x/crypto/ssh/testdata"
1519

@@ -317,3 +321,100 @@ func (*SuiteCommon) TestNewKnownHostsDbWithCert(c *C) {
317321
}
318322
}
319323
}
324+
325+
func TestHostKeyCallbackHelper(t *testing.T) {
326+
cb1 := ssh.FixedHostKey(nil)
327+
tests := []struct {
328+
name string
329+
cb ssh.HostKeyCallback
330+
algos []string
331+
fallback func(files ...string) (ssh.HostKeyCallback, error)
332+
cc *ssh.ClientConfig
333+
want *ssh.ClientConfig
334+
wantErr string
335+
}{
336+
{
337+
name: "keep existing callback if set",
338+
cb: cb1,
339+
cc: &ssh.ClientConfig{},
340+
want: &ssh.ClientConfig{
341+
HostKeyCallback: cb1,
342+
},
343+
},
344+
{
345+
name: "create new client config is one isn't provided",
346+
cb: cb1,
347+
cc: nil,
348+
want: &ssh.ClientConfig{
349+
HostKeyCallback: cb1,
350+
},
351+
},
352+
{
353+
name: "respect pre-set algos",
354+
cb: cb1,
355+
algos: []string{"foo"},
356+
cc: &ssh.ClientConfig{},
357+
want: &ssh.ClientConfig{
358+
HostKeyCallback: cb1,
359+
HostKeyAlgorithms: []string{"foo"},
360+
},
361+
},
362+
{
363+
name: "no callback is set, call fallback",
364+
cc: &ssh.ClientConfig{},
365+
fallback: func(files ...string) (ssh.HostKeyCallback, error) {
366+
return cb1, nil
367+
},
368+
want: &ssh.ClientConfig{
369+
HostKeyCallback: cb1,
370+
},
371+
},
372+
{
373+
name: "no callback is set with nil client config",
374+
fallback: func(files ...string) (ssh.HostKeyCallback, error) {
375+
return cb1, nil
376+
},
377+
want: &ssh.ClientConfig{
378+
HostKeyCallback: cb1,
379+
},
380+
},
381+
{
382+
name: "algos with no callback, call fallback",
383+
algos: []string{"bar"},
384+
cc: &ssh.ClientConfig{},
385+
fallback: func(files ...string) (ssh.HostKeyCallback, error) {
386+
return cb1, nil
387+
},
388+
want: &ssh.ClientConfig{
389+
HostKeyCallback: cb1,
390+
HostKeyAlgorithms: []string{"bar"},
391+
},
392+
},
393+
}
394+
395+
for _, tc := range tests {
396+
t.Run(tc.name, func(t *testing.T) {
397+
helper := HostKeyCallbackHelper{
398+
HostKeyCallback: tc.cb,
399+
HostKeyAlgorithms: tc.algos,
400+
fallback: tc.fallback,
401+
}
402+
403+
got, gotErr := helper.SetHostKeyCallback(tc.cc)
404+
405+
if tc.wantErr == "" {
406+
require.NoError(t, gotErr)
407+
require.NotNil(t, got)
408+
409+
wantFunc := runtime.FuncForPC(reflect.ValueOf(tc.want.HostKeyCallback).Pointer()).Name()
410+
gotFunc := runtime.FuncForPC(reflect.ValueOf(got.HostKeyCallback).Pointer()).Name()
411+
assert.Equal(t, wantFunc, gotFunc)
412+
413+
assert.Equal(t, tc.want.HostKeyAlgorithms, got.HostKeyAlgorithms)
414+
} else {
415+
assert.ErrorContains(t, gotErr, tc.wantErr)
416+
assert.Nil(t, got)
417+
}
418+
})
419+
}
420+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.