sshpoke/internal/server/driver/ssh/sshproto/auth.go
2023-11-18 17:51:04 +03:00

92 lines
1.8 KiB
Go

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
}