mirror of
https://github.com/hacdias/webdav.git
synced 2026-09-22 03:20:41 +08:00
feat: allow disabling password check for delegated authentication
This commit is contained in:
@@ -106,7 +106,14 @@ cors:
|
||||
- Content-Length
|
||||
- Content-Range
|
||||
|
||||
# The list of users. If users is empty, then there will be no authentication.
|
||||
# The list of users. If the list is empty, then there will be no authentication.
|
||||
# Otherwise, basic authentication will automatically be configured.
|
||||
#
|
||||
# If you're delegating the authentication to a different service, you can proxy
|
||||
# the username using basic authentication, and then disable webdav's password
|
||||
# check using the option:
|
||||
#
|
||||
# noPassword: true
|
||||
users:
|
||||
# Example 'admin' user with plaintext password.
|
||||
- username: admin
|
||||
|
||||
+3
-1
@@ -32,6 +32,7 @@ type Config struct {
|
||||
Key string
|
||||
Prefix string
|
||||
NoSniff bool
|
||||
NoPassword bool
|
||||
Log Log
|
||||
CORS CORS
|
||||
Users []User
|
||||
@@ -77,6 +78,7 @@ func ParseConfig(filename string, flags *pflag.FlagSet) (*Config, error) {
|
||||
v.SetDefault("Permissions", "R")
|
||||
v.SetDefault("Debug", false)
|
||||
v.SetDefault("NoSniff", false)
|
||||
v.SetDefault("NoPassword", false)
|
||||
v.SetDefault("Log.Format", "console")
|
||||
v.SetDefault("Log.Outputs", []string{"stderr"})
|
||||
v.SetDefault("Log.Colors", true)
|
||||
@@ -159,7 +161,7 @@ func (c *Config) Validate() error {
|
||||
}
|
||||
|
||||
for _, u := range c.Users {
|
||||
err := u.Validate()
|
||||
err := u.Validate(c.NoPassword)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid config: %w", err)
|
||||
}
|
||||
|
||||
+9
-3
@@ -17,12 +17,14 @@ type handlerUser struct {
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
user *handlerUser
|
||||
users map[string]*handlerUser
|
||||
noPassword bool
|
||||
user *handlerUser
|
||||
users map[string]*handlerUser
|
||||
}
|
||||
|
||||
func NewHandler(c *Config) (http.Handler, error) {
|
||||
h := &Handler{
|
||||
noPassword: c.NoPassword,
|
||||
user: &handlerUser{
|
||||
User: User{
|
||||
UserPermissions: c.UserPermissions,
|
||||
@@ -67,6 +69,10 @@ func NewHandler(c *Config) (http.Handler, error) {
|
||||
zap.L().Warn("unprotected config: no users have been set, so no authentication will be used")
|
||||
}
|
||||
|
||||
if c.NoPassword {
|
||||
zap.L().Warn("unprotected config: password check is disabled, only intended when delegating authentication to another service")
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
@@ -92,7 +98,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if !user.checkPassword(password) {
|
||||
if !h.noPassword && !user.checkPassword(password) {
|
||||
zap.L().Info("invalid password", zap.String("username", username), zap.String("remote_address", r.RemoteAddr))
|
||||
http.Error(w, "Not authorized", http.StatusUnauthorized)
|
||||
return
|
||||
|
||||
@@ -183,6 +183,40 @@ users:
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerAuthenticationNoPassword(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dir := makeTestDirectory(t, map[string][]byte{
|
||||
"foo.txt": []byte("foo"),
|
||||
"sub/bar.txt": []byte("bar"),
|
||||
})
|
||||
|
||||
srv := makeTestServer(t, fmt.Sprintf(`
|
||||
directory: %s
|
||||
noPassword: true
|
||||
permissions: CRUD
|
||||
|
||||
users:
|
||||
- username: basic
|
||||
`, dir))
|
||||
|
||||
t.Run("Basic Auth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := gowebdav.NewClient(srv.URL, "basic", "")
|
||||
files, err := client.ReadDir("/")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, files, 2)
|
||||
})
|
||||
|
||||
t.Run("Unauthorized Wrong User", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := gowebdav.NewClient(srv.URL, "wrong", "")
|
||||
_, err := client.ReadDir("/")
|
||||
require.ErrorContains(t, err, "401")
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerRules(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
+2
-2
@@ -24,12 +24,12 @@ func (u User) checkPassword(input string) bool {
|
||||
return u.Password == input
|
||||
}
|
||||
|
||||
func (u *User) Validate() error {
|
||||
func (u *User) Validate(noPassword bool) error {
|
||||
if u.Username == "" {
|
||||
return errors.New("invalid user: username must be set")
|
||||
}
|
||||
|
||||
if u.Password == "" {
|
||||
if u.Password == "" && !noPassword {
|
||||
return fmt.Errorf("invalid user %q: password must be set", u.Username)
|
||||
} else if strings.HasPrefix(u.Password, "{env}") {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user