105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/go-crypt/crypt"
|
|
"golang.org/x/crypto/ssh"
|
|
|
|
"git.maze.io/maze/conduit/logger"
|
|
"git.maze.io/maze/conduit/ssh/sshutil"
|
|
)
|
|
|
|
type passwordFile map[string]string
|
|
|
|
func PasswordFile(name string) (Password, error) {
|
|
f, err := os.Open(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s := bufio.NewScanner(f)
|
|
p := make(passwordFile)
|
|
for s.Scan() {
|
|
line := s.Text()
|
|
if len(line) == 0 || line[0] == '#' || strings.HasPrefix(line, "//") {
|
|
continue
|
|
}
|
|
if i := strings.IndexByte(line, ':'); i > 0 {
|
|
p[line[:i]] = line[i+1:]
|
|
}
|
|
}
|
|
return p, s.Err()
|
|
}
|
|
|
|
func (auth passwordFile) VerifyPassword(meta ssh.ConnMetadata, password string) (Principal, error) {
|
|
encodedDigest := auth[meta.User()]
|
|
if ok, err := crypt.CheckPasswordWithPlainText(password, encodedDigest); err != nil {
|
|
return nil, err
|
|
} else if !ok {
|
|
return nil, ErrUnauthorized
|
|
}
|
|
return MakePasswordPrincipal(meta), nil
|
|
}
|
|
|
|
type publibKeyFile map[string][]ssh.PublicKey
|
|
|
|
func PublicKeyFile(name string) (PublicKey, error) {
|
|
log := logger.StandardLog.Value("path", name)
|
|
log.Trace("Parsing public keys file")
|
|
|
|
f, err := os.Open(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var (
|
|
s = bufio.NewScanner(f)
|
|
p = make(publibKeyFile)
|
|
lineno int
|
|
)
|
|
for s.Scan() {
|
|
line := s.Text()
|
|
lineno++
|
|
if len(line) == 0 || line[0] == '#' || strings.HasPrefix(line, "//") {
|
|
continue
|
|
}
|
|
if i := strings.IndexByte(line, ':'); i > 0 {
|
|
//k, err := ssh.ParsePublicKey([]byte(line[i+1:]))
|
|
k, _, _, _, err := ssh.ParseAuthorizedKey([]byte(line[i+1:]))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("auth: invalid public key in %s:%d: %w", name, lineno, err)
|
|
}
|
|
log.Values(logger.Values{
|
|
"user": line[:i],
|
|
"key": k.Type(),
|
|
}).Trace("Parsed authorized public key")
|
|
p[line[:i]] = append(p[line[:i]], k)
|
|
}
|
|
}
|
|
return p, s.Err()
|
|
}
|
|
|
|
func (auth publibKeyFile) VerifyPublicKey(meta ssh.ConnMetadata, key ssh.PublicKey) (Principal, error) {
|
|
log := logger.StandardLog.Values(logger.Values{
|
|
"client": meta.RemoteAddr().String(),
|
|
"key_type": sshutil.KeyType(key),
|
|
"key_bits": sshutil.KeyBits(key),
|
|
"user": meta.User(),
|
|
"version": string(meta.ClientVersion()),
|
|
})
|
|
log.Debug("Verifying user public key")
|
|
|
|
blob := key.Marshal()
|
|
keys := auth[meta.User()]
|
|
for _, other := range keys {
|
|
if bytes.Equal(other.Marshal(), blob) {
|
|
return MakePublicKeyPrincipal(meta, key), nil
|
|
}
|
|
}
|
|
return nil, ErrUnauthorized
|
|
}
|