mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
Remove unused-parameter exclusion for `ctx` in revive linter. --------- Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com> Co-authored-by: Matthieu MOREL <matthieu.morel35@gmail.com>
90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
// Package auth provides authentication and authorization constructs.
|
|
package auth
|
|
|
|
import (
|
|
"context"
|
|
"crypto/subtle"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/tg123/go-htpasswd"
|
|
|
|
"github.com/kopia/kopia/repo"
|
|
"github.com/kopia/kopia/repo/logging"
|
|
)
|
|
|
|
var log = logging.Module("auth")
|
|
|
|
// Authenticator verifies that the provided username/password is valid.
|
|
type Authenticator interface {
|
|
IsValid(ctx context.Context, rep repo.Repository, username, password string) bool
|
|
Refresh(ctx context.Context) error
|
|
}
|
|
|
|
type singleUserAuthenticator struct {
|
|
expectedUsernameBytes []byte
|
|
expectedPasswordBytes []byte
|
|
}
|
|
|
|
func (a *singleUserAuthenticator) IsValid(_ context.Context, _ repo.Repository, username, password string) bool {
|
|
return subtle.ConstantTimeCompare([]byte(username), a.expectedUsernameBytes)*
|
|
subtle.ConstantTimeCompare([]byte(password), a.expectedPasswordBytes) == 1
|
|
}
|
|
|
|
func (a *singleUserAuthenticator) Refresh(_ context.Context) error {
|
|
return nil
|
|
}
|
|
|
|
// AuthenticateSingleUser returns an Authenticator that only allows one username/password combination.
|
|
func AuthenticateSingleUser(expectedUsername, expectedPassword string) Authenticator {
|
|
return &singleUserAuthenticator{[]byte(expectedUsername), []byte(expectedPassword)}
|
|
}
|
|
|
|
type combinedAuthenticator []Authenticator
|
|
|
|
func (c combinedAuthenticator) IsValid(ctx context.Context, rep repo.Repository, username, password string) bool {
|
|
for _, a := range c {
|
|
if a.IsValid(ctx, rep, username, password) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (c combinedAuthenticator) Refresh(ctx context.Context) error {
|
|
for _, a := range c {
|
|
if err := a.Refresh(ctx); err != nil {
|
|
return errors.Wrap(err, "error refreshing authenticator")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CombineAuthenticators return authenticator that applies the provided authenticators in order
|
|
// and returns true if any of them accepts given username/password combination.
|
|
func CombineAuthenticators(authenticators ...Authenticator) Authenticator {
|
|
if len(authenticators) == 0 {
|
|
return nil
|
|
}
|
|
|
|
return combinedAuthenticator(authenticators)
|
|
}
|
|
|
|
type htpasswdAuthenticator struct {
|
|
f *htpasswd.File
|
|
}
|
|
|
|
func (a htpasswdAuthenticator) IsValid(_ context.Context, _ repo.Repository, username, password string) bool {
|
|
return a.f.Match(username, password)
|
|
}
|
|
|
|
func (a htpasswdAuthenticator) Refresh(_ context.Context) error {
|
|
return errors.Wrap(a.f.Reload(nil), "error reloading password file")
|
|
}
|
|
|
|
// AuthenticateHtpasswdFile returns an authenticator that accepts users in the provided htpasswd file.
|
|
func AuthenticateHtpasswdFile(f *htpasswd.File) Authenticator {
|
|
return htpasswdAuthenticator{f}
|
|
}
|