mirror of https://github.com/jetkvm/kvm.git
72 lines
1.5 KiB
Go
72 lines
1.5 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"strings"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
// ValidSSHKeyTypes is a list of valid SSH key types
|
|
//
|
|
// Please make sure that all the types in this list are supported by dropbear
|
|
// https://github.com/mkj/dropbear/blob/003c5fcaabc114430d5d14142e95ffdbbd2d19b6/src/signkey.c#L37
|
|
//
|
|
// ssh-dss is not allowed here as it's insecure
|
|
var ValidSSHKeyTypes = []string{
|
|
ssh.KeyAlgoRSA,
|
|
ssh.KeyAlgoED25519,
|
|
ssh.KeyAlgoECDSA256,
|
|
ssh.KeyAlgoECDSA384,
|
|
ssh.KeyAlgoECDSA521,
|
|
}
|
|
|
|
// ValidateSSHKey validates authorized_keys file content
|
|
func ValidateSSHKey(sshKey string) error {
|
|
// validate SSH key
|
|
var (
|
|
hasValidPublicKey = false
|
|
lastError = fmt.Errorf("no valid SSH key found")
|
|
)
|
|
for _, key := range strings.Split(sshKey, "\n") {
|
|
key = strings.TrimSpace(key)
|
|
|
|
// skip empty lines and comments
|
|
if key == "" || strings.HasPrefix(key, "#") {
|
|
continue
|
|
}
|
|
|
|
parsedPublicKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key))
|
|
if err != nil {
|
|
lastError = err
|
|
continue
|
|
}
|
|
|
|
if parsedPublicKey == nil {
|
|
continue
|
|
}
|
|
|
|
parsedType := parsedPublicKey.Type()
|
|
textType := strings.Fields(key)[0]
|
|
|
|
if parsedType != textType {
|
|
lastError = fmt.Errorf("parsed SSH key type %s does not match type in text %s", parsedType, textType)
|
|
continue
|
|
}
|
|
|
|
if !slices.Contains(ValidSSHKeyTypes, parsedType) {
|
|
lastError = fmt.Errorf("invalid SSH key type: %s", parsedType)
|
|
continue
|
|
}
|
|
|
|
hasValidPublicKey = true
|
|
}
|
|
|
|
if !hasValidPublicKey {
|
|
return lastError
|
|
}
|
|
|
|
return nil
|
|
}
|