package sshproto import ( "errors" "fmt" "os" "path" "strings" "github.com/Neur0toxine/sshpoke/internal/server/driver/ssh/types" "golang.org/x/crypto/ssh" ) func AuthKeyFile(keyFile types.SmartPath) (ssh.AuthMethod, error) { key, err := readKey(keyFile) if err != nil { return nil, err } return ssh.PublicKeys(key), nil } func AuthKeyDir(keyDir types.SmartPath) (ssh.AuthMethod, error) { keys, err := readKeys(keyDir) if err != nil { return nil, err } return ssh.PublicKeys(keys...), nil } func AuthPassword(password string) ssh.AuthMethod { return ssh.Password(password) } func readKeys(keyDir types.SmartPath) ([]ssh.Signer, error) { dir, err := keyDir.Resolve(true) if err != nil { return nil, fmt.Errorf("cannot parse keys: %s", err) } entries, err := os.ReadDir(dir) if err != nil { return nil, fmt.Errorf("cannot read key directory: %s", err) } keys := []ssh.Signer{} for _, entry := range entries { if entry.IsDir() { continue } info, err := entry.Info() if err != nil { continue } if strings.HasSuffix(entry.Name(), ".pub") { continue } if entry.Name() == "config" { continue } if entry.Name() == "known_hosts" { continue } // this file is too small to be a private key if info.Size() < 256 { continue } key, err := readKey(types.SmartPath(path.Join(dir, entry.Name()))) if err != nil { continue } keys = append(keys, key) } if len(keys) == 0 { return nil, errors.New("no keys in the provided directory") } return keys, nil } func readKey(keyFile types.SmartPath) (ssh.Signer, error) { fileName, err := keyFile.Resolve(false) if err != nil { return nil, err } keyData, err := os.ReadFile(fileName) if err != nil { return nil, err } key, err := ssh.ParsePrivateKey(keyData) if err != nil { return nil, err } return key, nil }