diff options
author | Himbeer <himbeer@disroot.org> | 2024-11-16 23:17:27 +0100 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-11-17 16:32:50 +0100 |
commit | d0d39d2f9f3abb68eec146376b3233c8bc7c1cfa (patch) | |
tree | 70be515811406cdc3ba1ab8b56d3c6eccb2f0d59 /plugin_auth.go | |
parent | e7d92562fcf05e4f9b7f6ba29b7cda529aab49bc (diff) |
Allow plugins to implement authentication backends
Design decisions:
* Config option specifies which of the registered backends is used
* Name conflicts (including with builtins) make the backend registration
fail
* Builtin backends are not moved to plugins to avoid breaking existing
setups confusion in general
* Builtin backends are exposed to plugins (and have been for some time);
Important information and internal methods are hidden to prevent
interference from malicious plugins
See doc/auth_backends.md and the related interface and function
documentation for details.
Closes #127.
Diffstat (limited to 'plugin_auth.go')
-rw-r--r-- | plugin_auth.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/plugin_auth.go b/plugin_auth.go new file mode 100644 index 0000000..ec58189 --- /dev/null +++ b/plugin_auth.go @@ -0,0 +1,74 @@ +package proxy + +import ( + "errors" + "fmt" + "sync" +) + +var ( + ErrEmptyAuthBackendName = errors.New("auth backend name is empty") + ErrNilAuthBackend = errors.New("auth backend is nil") + ErrBuiltinAuthBackend = errors.New("auth backend name collision with builtin") +) + +var ( + authBackends map[string]AuthBackend + authBackendsMu sync.Mutex + authBackendsOnce sync.Once +) + +// Auth returns an authentication backend by name or false if it doesn't exist. +func Auth(name string) (AuthBackend, bool) { + authBackendsMu.Lock() + defer authBackendsMu.Unlock() + + ab, ok := authBackends[name] + return ab, ok +} + +// RegisterAuthBackend registers a new authentication backend implementation. +// The name must be unique, non-empty and must not collide +// with a builtin authentication backend. +// The authentication backend must be non-nil. +// Registered backends can be enabled by specifying their name +// in the AuthBackend config option. +// Backend-specific configuration is handled by the calling plugin's +// configuration mechanism at initialization time. +// Backends must be registered at initialization time +// (before the init functions return). +// Backends registered after initialization time will not be available +// to the user. +func RegisterAuthBackend(name string, ab AuthBackend) error { + initAuthBackends() + + if name == "" { + return ErrEmptyAuthBackendName + } + if ab == nil { + return ErrNilAuthBackend + } + + if name == "files" || name == "mtsqlite3" || name == "mtpostgresql" { + return ErrBuiltinAuthBackend + } + + if _, ok := authBackends[name]; ok { + return fmt.Errorf("duplicate auth backend %s", name) + } + + authBackendsMu.Lock() + defer authBackendsMu.Unlock() + + authBackends[name] = ab + return nil +} + +func initAuthBackends() { + authBackendsOnce.Do(func() { + authBackendsMu.Lock() + defer authBackendsMu.Unlock() + + authBackends = make(map[string]AuthBackend) + }) +} |