Skip to content

Commit ff2b617

Browse files
committed
Implement ssh host key check
1 parent 5be467a commit ff2b617

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

cmd/litestream/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ type ReplicaConfig struct {
362362
User string `yaml:"user"`
363363
Password string `yaml:"password"`
364364
KeyPath string `yaml:"key-path"`
365+
HostKey string `yaml:"host-key"`
365366

366367
// Encryption identities and recipients
367368
Age struct {
@@ -663,6 +664,7 @@ func newSFTPReplicaClientFromConfig(c *ReplicaConfig, r *litestream.Replica) (_
663664
client.Password = password
664665
client.Path = path
665666
client.KeyPath = c.KeyPath
667+
client.HostKey = c.HostKey
666668
return client, nil
667669
}
668670

sftp/replica_client.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"io"
8+
"log/slog"
89
"net"
910
"os"
1011
"path"
@@ -39,6 +40,7 @@ type ReplicaClient struct {
3940
Password string
4041
Path string
4142
KeyPath string
43+
HostKey string
4244
DialTimeout time.Duration
4345
}
4446

@@ -68,9 +70,20 @@ func (c *ReplicaClient) Init(ctx context.Context) (_ *sftp.Client, err error) {
6870
}
6971

7072
// Build SSH configuration & auth methods
73+
var hostkey ssh.HostKeyCallback
74+
if c.HostKey != "" {
75+
var pubkey, _, _, _, err = ssh.ParseAuthorizedKey([]byte(c.HostKey))
76+
if err != nil {
77+
return nil, fmt.Errorf("cannot parse sftp host key: %w", err)
78+
}
79+
hostkey = ssh.FixedHostKey(pubkey)
80+
} else {
81+
slog.Warn("sftp host key not verified", "host", c.Host)
82+
hostkey = ssh.InsecureIgnoreHostKey()
83+
}
7184
config := &ssh.ClientConfig{
7285
User: c.User,
73-
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
86+
HostKeyCallback: hostkey,
7487
BannerCallback: ssh.BannerDisplayStderr(),
7588
}
7689
if c.Password != "" {

0 commit comments

Comments
 (0)