62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
package sshd
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
type Auth interface {
|
|
AllowAnonymous() bool
|
|
Check(string) (bool, error)
|
|
}
|
|
|
|
func MakeAuth(auth Auth) *ssh.ServerConfig {
|
|
config := ssh.ServerConfig{
|
|
NoClientAuth: false,
|
|
// Auth-related things should be constant-time to avoid timing attacks.
|
|
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
|
fingerprint := Fingerprint(key)
|
|
ok, err := auth.Check(fingerprint)
|
|
if !ok {
|
|
return nil, err
|
|
}
|
|
perm := &ssh.Permissions{Extensions: map[string]string{"fingerprint": fingerprint}}
|
|
return perm, nil
|
|
},
|
|
KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
|
|
if !auth.AllowAnonymous() {
|
|
return nil, errors.New("public key authentication required")
|
|
}
|
|
return nil, nil
|
|
},
|
|
}
|
|
|
|
return &config
|
|
}
|
|
|
|
func MakeNoAuth() *ssh.ServerConfig {
|
|
config := ssh.ServerConfig{
|
|
NoClientAuth: false,
|
|
// Auth-related things should be constant-time to avoid timing attacks.
|
|
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
|
perm := &ssh.Permissions{Extensions: map[string]string{"fingerprint": Fingerprint(key)}}
|
|
return perm, nil
|
|
},
|
|
KeyboardInteractiveCallback: func(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {
|
|
return nil, nil
|
|
},
|
|
}
|
|
|
|
return &config
|
|
}
|
|
|
|
func Fingerprint(k ssh.PublicKey) string {
|
|
hash := sha1.Sum(k.Marshal())
|
|
r := fmt.Sprintf("% x", hash)
|
|
return strings.Replace(r, " ", ":", -1)
|
|
}
|