@@ -176,39 +176,41 @@ func nextWord(line []byte) (string, []byte) {
176176 return string (line [:i ]), bytes .TrimSpace (line [i :])
177177}
178178
179- func parseLine (line []byte ) (marker , host string , key ssh.PublicKey , err error ) {
179+ func parseLine (line []byte ) (marker , host , comments string , key ssh.PublicKey , err error ) {
180180 if w , next := nextWord (line ); w == markerCert || w == markerRevoked {
181181 marker = w
182182 line = next
183183 }
184184
185185 host , line = nextWord (line )
186186 if len (line ) == 0 {
187- return "" , "" , nil , errors .New ("knownhosts: missing host pattern" )
187+ return "" , "" , "" , nil , errors .New ("knownhosts: missing host pattern" )
188188 }
189189
190190 // ignore the keytype as it's in the key blob anyway.
191191 _ , line = nextWord (line )
192192 if len (line ) == 0 {
193- return "" , "" , nil , errors .New ("knownhosts: missing key type pattern" )
193+ return "" , "" , "" , nil , errors .New ("knownhosts: missing key type pattern" )
194194 }
195195
196- keyBlob , _ := nextWord (line )
196+ keyBlob , line := nextWord (line )
197197
198198 keyBytes , err := base64 .StdEncoding .DecodeString (keyBlob )
199199 if err != nil {
200- return "" , "" , nil , err
200+ return "" , "" , "" , nil , err
201201 }
202202 key , err = ssh .ParsePublicKey (keyBytes )
203203 if err != nil {
204- return "" , "" , nil , err
204+ return "" , "" , "" , nil , err
205205 }
206+ // the rest of the line is the comment, and may include whitespace.
207+ restOfLine := string (bytes .TrimSpace (line ))
206208
207- return marker , host , key , nil
209+ return marker , host , restOfLine , key , nil
208210}
209211
210212func (db * hostKeyDB ) parseLine (line []byte , filename string , linenum int ) error {
211- marker , pattern , key , err := parseLine (line )
213+ marker , pattern , comments , key , err := parseLine (line )
212214 if err != nil {
213215 return err
214216 }
@@ -218,6 +220,7 @@ func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error
218220 Key : key ,
219221 Filename : filename ,
220222 Line : linenum ,
223+ Comments : comments ,
221224 }
222225
223226 return nil
@@ -229,6 +232,7 @@ func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error
229232 Filename : filename ,
230233 Line : linenum ,
231234 Key : key ,
235+ Comments : comments ,
232236 },
233237 }
234238
@@ -241,7 +245,6 @@ func (db *hostKeyDB) parseLine(line []byte, filename string, linenum int) error
241245 if err != nil {
242246 return err
243247 }
244-
245248 db .lines = append (db .lines , entry )
246249 return nil
247250}
@@ -290,10 +293,11 @@ type KnownKey struct {
290293 Key ssh.PublicKey
291294 Filename string
292295 Line int
296+ Comments string
293297}
294298
295299func (k * KnownKey ) String () string {
296- return fmt .Sprintf ("%s:%d: %s" , k .Filename , k .Line , serialize (k .Key ))
300+ return fmt .Sprintf ("%s:%d: %s %s " , k .Filename , k .Line , serialize (k .Key ), k . Comments )
297301}
298302
299303// KeyError is returned if we did not find the key in the host key
@@ -435,6 +439,26 @@ func New(files ...string) (ssh.HostKeyCallback, error) {
435439 return certChecker .CheckHostKey , nil
436440}
437441
442+ func NewKnownKeys (files ... string ) ([]KnownKey , error ) {
443+ db := newHostKeyDB ()
444+ for _ , fn := range files {
445+ f , err := os .Open (fn )
446+ if err != nil {
447+ return nil , err
448+ }
449+ defer f .Close ()
450+ if err := db .Read (f , fn ); err != nil {
451+ return nil , err
452+ }
453+ }
454+
455+ keys := make ([]KnownKey , 0 , len (db .lines ))
456+ for _ , l := range db .lines {
457+ keys = append (keys , l .knownKey )
458+ }
459+ return keys , nil
460+ }
461+
438462// Normalize normalizes an address into the form used in known_hosts
439463func Normalize (address string ) string {
440464 host , port , err := net .SplitHostPort (address )
0 commit comments