| 68 | } |
| 69 | |
| 70 | func (cfg *SSHConfig) LoadHostKeys() ([]ssh.Signer, error) { |
| 71 | var hostKeys []ssh.Signer |
| 72 | for index, hostKey := range cfg.HostKeys { |
| 73 | if strings.TrimSpace(hostKey)[:5] != "-----" { |
| 74 | // We are deliberalely loading a dynamic file here. |
| 75 | fh, err := os.Open(hostKey) //nolint:gosec |
| 76 | if err != nil { |
| 77 | return nil, fmt.Errorf("failed to load host key %s (%w)", hostKey, err) |
| 78 | } |
| 79 | hostKeyData, err := io.ReadAll(fh) |
| 80 | if err != nil { |
| 81 | _ = fh.Close() |
| 82 | return nil, fmt.Errorf("failed to load host key %s (%w)", hostKey, err) |
| 83 | } |
| 84 | if err = fh.Close(); err != nil { |
| 85 | return nil, fmt.Errorf("failed to close host key file %s (%w)", hostKey, err) |
| 86 | } |
| 87 | hostKey = string(hostKeyData) |
| 88 | } |
| 89 | private, err := ssh.ParsePrivateKey([]byte(hostKey)) |
| 90 | if err != nil { |
| 91 | return nil, fmt.Errorf("failed to parse host key (%w)", err) |
| 92 | } |
| 93 | keyType := private.PublicKey().Type() |
| 94 | |
| 95 | if err := SSHKeyAlgo(keyType).Validate(); err != nil { |
| 96 | return nil, fmt.Errorf("unsupported host key algorithm %s on host key %d", keyType, index) |
| 97 | } |
| 98 | hostKeys = append(hostKeys, private) |
| 99 | } |
| 100 | return hostKeys, nil |
| 101 | } |
| 102 | |
| 103 | // Validate validates the configuration and returns an error if invalid. |
| 104 | func (cfg SSHConfig) Validate() error { |