ssh-chat/auth.go

99 lines
2.2 KiB
Go
Raw Normal View History

2015-01-02 03:51:34 +01:00
package main
import (
"errors"
"sync"
"github.com/shazow/ssh-chat/sshd"
"golang.org/x/crypto/ssh"
2015-01-02 03:51:34 +01:00
)
// The error returned a key is checked that is not whitelisted, with whitelisting required.
var ErrNotWhitelisted = errors.New("not whitelisted")
// The error returned a key is checked that is banned.
var ErrBanned = errors.New("banned")
// AuthKey is the type that our lookups are keyed against.
type AuthKey string
// NewAuthKey returns an AuthKey from an ssh.PublicKey.
func NewAuthKey(key ssh.PublicKey) AuthKey {
// FIXME: Is there a way to index pubkeys without marshal'ing them into strings?
return AuthKey(string(key.Marshal()))
}
2015-01-02 03:51:34 +01:00
// Auth stores fingerprint lookups
type Auth struct {
sshd.Auth
sync.RWMutex
whitelist map[AuthKey]struct{}
banned map[AuthKey]struct{}
ops map[AuthKey]struct{}
2015-01-02 03:51:34 +01:00
}
2015-01-03 06:40:53 +01:00
// NewAuth creates a new default Auth.
func NewAuth() *Auth {
return &Auth{
whitelist: make(map[AuthKey]struct{}),
banned: make(map[AuthKey]struct{}),
ops: make(map[AuthKey]struct{}),
2015-01-03 06:40:53 +01:00
}
}
2015-01-02 03:51:34 +01:00
// AllowAnonymous determines if anonymous users are permitted.
func (a Auth) AllowAnonymous() bool {
a.RLock()
ok := len(a.whitelist) == 0
a.RUnlock()
return ok
}
// Check determines if a pubkey fingerprint is permitted.
func (a Auth) Check(key ssh.PublicKey) (bool, error) {
authkey := NewAuthKey(key)
2015-01-02 03:51:34 +01:00
a.RLock()
defer a.RUnlock()
if len(a.whitelist) > 0 {
// Only check whitelist if there is something in it, otherwise it's disabled.
_, whitelisted := a.whitelist[authkey]
2015-01-02 03:51:34 +01:00
if !whitelisted {
return false, ErrNotWhitelisted
2015-01-02 03:51:34 +01:00
}
}
_, banned := a.banned[authkey]
2015-01-02 03:51:34 +01:00
if banned {
return false, ErrBanned
2015-01-02 03:51:34 +01:00
}
return true, nil
}
// Op will set a fingerprint as a known operator.
func (a *Auth) Op(key ssh.PublicKey) {
authkey := NewAuthKey(key)
2015-01-02 03:51:34 +01:00
a.Lock()
a.ops[authkey] = struct{}{}
2015-01-02 03:51:34 +01:00
a.Unlock()
}
// Whitelist will set a fingerprint as a whitelisted user.
func (a *Auth) Whitelist(key ssh.PublicKey) {
authkey := NewAuthKey(key)
2015-01-02 03:51:34 +01:00
a.Lock()
a.whitelist[authkey] = struct{}{}
2015-01-02 03:51:34 +01:00
a.Unlock()
}
// Ban will set a fingerprint as banned.
func (a *Auth) Ban(key ssh.PublicKey) {
authkey := NewAuthKey(key)
2015-01-02 03:51:34 +01:00
a.Lock()
a.banned[authkey] = struct{}{}
2015-01-02 03:51:34 +01:00
a.Unlock()
}