Skip to content

Commit 6625e64

Browse files
committed
Support cert authorities
1 parent e73fcfc commit 6625e64

File tree

1 file changed

+63
-11
lines changed

1 file changed

+63
-11
lines changed

knownhosts.go

+63-11
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"io"
10+
"io/ioutil"
1011
"net"
1112
"sort"
1213
"strings"
@@ -34,12 +35,17 @@ func (hkcb HostKeyCallback) HostKeyCallback() ssh.HostKeyCallback {
3435
return ssh.HostKeyCallback(hkcb)
3536
}
3637

38+
type PublicKey struct {
39+
ssh.PublicKey
40+
cert bool
41+
}
42+
3743
// HostKeys returns a slice of known host public keys for the supplied host:port
3844
// found in the known_hosts file(s), or an empty slice if the host is not
3945
// already known. For hosts that have multiple known_hosts entries (for
4046
// different key types), the result will be sorted by known_hosts filename and
4147
// line number.
42-
func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []ssh.PublicKey) {
48+
func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []PublicKey) {
4349
var keyErr *xknownhosts.KeyError
4450
placeholderAddr := &net.TCPAddr{IP: []byte{0, 0, 0, 0}}
4551
placeholderPubKey := &fakePublicKey{}
@@ -53,14 +59,47 @@ func (hkcb HostKeyCallback) HostKeys(hostWithPort string) (keys []ssh.PublicKey)
5359
return (kkeys[i].Filename == kkeys[j].Filename && kkeys[i].Line < kkeys[j].Line)
5460
}
5561
sort.Slice(kkeys, knownKeyLess)
56-
keys = make([]ssh.PublicKey, len(kkeys))
57-
for n := range kkeys {
58-
keys[n] = kkeys[n].Key
62+
keys = make([]PublicKey, len(kkeys))
63+
for n, k := range kkeys {
64+
content, err := ioutil.ReadFile(k.Filename)
65+
if err != nil {
66+
continue
67+
}
68+
lines := strings.Split(string(content), "\n")
69+
line := lines[k.Line-1]
70+
isCert := strings.HasPrefix(line, "@cert-authority")
71+
72+
keys[n] = PublicKey{
73+
PublicKey: k.Key,
74+
cert: isCert,
75+
}
5976
}
6077
}
6178
return keys
6279
}
6380

81+
func keyTypeToCertType(keyType string) string {
82+
switch keyType {
83+
case ssh.KeyAlgoRSA:
84+
return ssh.CertAlgoRSAv01
85+
case ssh.KeyAlgoDSA:
86+
return ssh.CertAlgoDSAv01
87+
case ssh.KeyAlgoECDSA256:
88+
return ssh.CertAlgoECDSA256v01
89+
case ssh.KeyAlgoSKECDSA256:
90+
return ssh.CertAlgoSKECDSA256v01
91+
case ssh.KeyAlgoECDSA384:
92+
return ssh.CertAlgoECDSA384v01
93+
case ssh.KeyAlgoECDSA521:
94+
return ssh.CertAlgoECDSA521v01
95+
case ssh.KeyAlgoED25519:
96+
return ssh.CertAlgoED25519v01
97+
case ssh.KeyAlgoSKED25519:
98+
return ssh.CertAlgoSKED25519v01
99+
}
100+
return ""
101+
}
102+
64103
// HostKeyAlgorithms returns a slice of host key algorithms for the supplied
65104
// host:port found in the known_hosts file(s), or an empty slice if the host
66105
// is not already known. The result may be used in ssh.ClientConfig's
@@ -84,14 +123,27 @@ func (hkcb HostKeyCallback) HostKeyAlgorithms(hostWithPort string) (algos []stri
84123
}
85124
for _, key := range hostKeys {
86125
typ := key.Type()
87-
if typ == ssh.KeyAlgoRSA {
88-
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms,
89-
// not public key formats, so they can't appear as a PublicKey.Type.
90-
// The corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
91-
addAlgo(ssh.KeyAlgoRSASHA512)
92-
addAlgo(ssh.KeyAlgoRSASHA256)
126+
if key.cert {
127+
certType := keyTypeToCertType(typ)
128+
if certType == ssh.CertAlgoRSAv01 {
129+
130+
// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
131+
// Certificate.Type (or PublicKey.Type), but only in
132+
// ClientConfig.HostKeyAlgorithms.
133+
addAlgo(ssh.CertAlgoRSASHA256v01)
134+
addAlgo(ssh.CertAlgoRSASHA512v01)
135+
}
136+
addAlgo(certType)
137+
} else {
138+
if typ == ssh.KeyAlgoRSA {
139+
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms,
140+
// not public key formats, so they can't appear as a PublicKey.Type.
141+
// The corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
142+
addAlgo(ssh.KeyAlgoRSASHA512)
143+
addAlgo(ssh.KeyAlgoRSASHA256)
144+
}
145+
addAlgo(typ)
93146
}
94-
addAlgo(typ)
95147
}
96148
return algos
97149
}

0 commit comments

Comments
 (0)