func createHostKeyCallback()

in dubboctl/pkg/hub/ssh/dialer.go [378:442]


func createHostKeyCallback(hostKeyCallback HostKeyCallback) func(hostPort string, remote net.Addr, key ssh.PublicKey) error {
	return func(hostPort string, remote net.Addr, pubKey ssh.PublicKey) error {
		host, port := hostPort, "22"
		if _h, _p, err := net.SplitHostPort(host); err == nil {
			host, port = _h, _p
		}

		knownHosts := filepath.Join(homedir.Get(), ".ssh", "known_hosts")

		_, err := os.Stat(knownHosts)
		if err != nil && errors.Is(err, os.ErrNotExist) {
			if hostKeyCallback != nil && hostKeyCallback(hostPort, pubKey) == nil {
				return nil
			}
			return errUnknownServerKey
		}

		f, err := os.Open(knownHosts)
		if err != nil {
			return fmt.Errorf("failed to open known_hosts: %w", err)
		}
		defer f.Close()

		hashhost := knownhosts.HashHostname(host)

		var errs []error
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			_, hostPorts, _key, _, _, err := ssh.ParseKnownHosts(scanner.Bytes())
			if err != nil {
				errs = append(errs, err)
				continue
			}

			for _, hp := range hostPorts {
				h, p := hp, "22"
				if _h, _p, err := net.SplitHostPort(hp); err == nil {
					h, p = _h, _p
				}

				if (h == host || h == hashhost) && port == p {
					if pubKey.Type() != _key.Type() {
						errs = append(errs, fmt.Errorf("missmatch in type of a key"))
						continue
					}
					if bytes.Equal(_key.Marshal(), pubKey.Marshal()) {
						return nil
					}

					return errBadServerKey
				}
			}
		}

		if hostKeyCallback != nil && hostKeyCallback(hostPort, pubKey) == nil {
			return nil
		}

		if len(errs) > 0 {
			return fmt.Errorf("server is not trusted (%v)", errs)
		}

		return errUnknownServerKey
	}
}