fix: passthrough the minimum password length (#5236)
							parent
							
								
									7354eb6cf9
								
							
						
					
					
						commit
						bf37f88c32
					
				|  | @ -150,7 +150,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) { | |||
| 	} | ||||
| 
 | ||||
| 	if u == nil { | ||||
| 		pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength) | ||||
| 		pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | @ -186,7 +186,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) { | |||
| 
 | ||||
| 		// update the password when it doesn't match the current
 | ||||
| 		if p { | ||||
| 			pass, err := users.HashAndValidatePwd(a.Cred.Password, a.Settings.MinimumPasswordLength) | ||||
| 			pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv * | |||
| 	} | ||||
| 
 | ||||
| 	var hashedRandomPassword string | ||||
| 	hashedRandomPassword, err = users.HashAndValidatePwd(pwd, setting.MinimumPasswordLength) | ||||
| 	hashedRandomPassword, err = users.ValidateAndHashPwd(pwd, setting.MinimumPasswordLength) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -432,7 +432,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { | |||
| 
 | ||||
| 		log.Println("Randomly generated password for user 'admin':", pwd) | ||||
| 
 | ||||
| 		password, err = users.HashAndValidatePwd(pwd, set.MinimumPasswordLength) | ||||
| 		password, err = users.ValidateAndHashPwd(pwd, set.MinimumPasswordLength) | ||||
| 		checkErr(err) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ var usersAddCmd = &cobra.Command{ | |||
| 		checkErr(err) | ||||
| 		getUserDefaults(cmd.Flags(), &s.Defaults, false) | ||||
| 
 | ||||
| 		password, err := users.HashAndValidatePwd(args[1], s.MinimumPasswordLength) | ||||
| 		password, err := users.ValidateAndHashPwd(args[1], s.MinimumPasswordLength) | ||||
| 		checkErr(err) | ||||
| 
 | ||||
| 		user := &users.User{ | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ options you want to change.`, | |||
| 		} | ||||
| 
 | ||||
| 		if password != "" { | ||||
| 			user.Password, err = users.HashAndValidatePwd(password, s.MinimumPasswordLength) | ||||
| 			user.Password, err = users.ValidateAndHashPwd(password, s.MinimumPasswordLength) | ||||
| 			checkErr(err) | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,13 +1,16 @@ | |||
| package errors | ||||
| 
 | ||||
| import "errors" | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	ErrEmptyKey             = errors.New("empty key") | ||||
| 	ErrExist                = errors.New("the resource already exists") | ||||
| 	ErrNotExist             = errors.New("the resource does not exist") | ||||
| 	ErrEmptyPassword        = errors.New("password is empty") | ||||
| 	ErrShortPassword        = errors.New("password is too short") | ||||
| 	ErrEasyPassword         = errors.New("password is too easy") | ||||
| 	ErrEmptyUsername        = errors.New("username is empty") | ||||
| 	ErrEmptyRequest         = errors.New("empty request") | ||||
| 	ErrScopeIsRelative      = errors.New("scope is a relative path") | ||||
|  | @ -20,3 +23,11 @@ var ( | |||
| 	ErrSourceIsParent       = errors.New("source is parent") | ||||
| 	ErrRootUserDeletion     = errors.New("user with id 1 can't be deleted") | ||||
| ) | ||||
| 
 | ||||
| type ErrShortPassword struct { | ||||
| 	MinimumLength uint | ||||
| } | ||||
| 
 | ||||
| func (e ErrShortPassword) Error() string { | ||||
| 	return fmt.Sprintf("password is too short, minimum length is %d", e.MinimumLength) | ||||
| } | ||||
|  |  | |||
|  | @ -151,9 +151,9 @@ var signupHandler = func(_ http.ResponseWriter, r *http.Request, d *data) (int, | |||
| 
 | ||||
| 	d.settings.Defaults.Apply(user) | ||||
| 
 | ||||
| 	pwd, err := users.HashAndValidatePwd(info.Password, d.settings.MinimumPasswordLength) | ||||
| 	pwd, err := users.ValidateAndHashPwd(info.Password, d.settings.MinimumPasswordLength) | ||||
| 	if err != nil { | ||||
| 		return http.StatusInternalServerError, err | ||||
| 		return http.StatusBadRequest, err | ||||
| 	} | ||||
| 
 | ||||
| 	user.Password = pwd | ||||
|  |  | |||
|  | @ -125,13 +125,9 @@ var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d * | |||
| 		return http.StatusBadRequest, fbErrors.ErrEmptyPassword | ||||
| 	} | ||||
| 
 | ||||
| 	if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) { | ||||
| 		return http.StatusBadRequest, fbErrors.ErrShortPassword | ||||
| 	} | ||||
| 
 | ||||
| 	req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 	req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 	if err != nil { | ||||
| 		return http.StatusInternalServerError, err | ||||
| 		return http.StatusBadRequest, err | ||||
| 	} | ||||
| 
 | ||||
| 	userHome, err := d.settings.MakeUserDir(req.Data.Username, req.Data.Scope, d.server.Root) | ||||
|  | @ -167,17 +163,19 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request | |||
| 		} | ||||
| 
 | ||||
| 		if req.Data.Password != "" { | ||||
| 			req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 			req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 			if err != nil { | ||||
| 				return http.StatusBadRequest, err | ||||
| 			} | ||||
| 		} else { | ||||
| 			var suser *users.User | ||||
| 			suser, err = d.store.Users.Get(d.server.Root, d.raw.(uint)) | ||||
| 			if err != nil { | ||||
| 				return http.StatusInternalServerError, err | ||||
| 			} | ||||
| 			req.Data.Password = suser.Password | ||||
| 		} | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return http.StatusInternalServerError, err | ||||
| 		} | ||||
| 
 | ||||
| 		req.Which = []string{} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -190,13 +188,9 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request | |||
| 				return http.StatusForbidden, nil | ||||
| 			} | ||||
| 
 | ||||
| 			if len(req.Data.Password) < int(d.settings.MinimumPasswordLength) { | ||||
| 				return http.StatusBadRequest, fbErrors.ErrShortPassword | ||||
| 			} | ||||
| 
 | ||||
| 			req.Data.Password, err = users.HashAndValidatePwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 			req.Data.Password, err = users.ValidateAndHashPwd(req.Data.Password, d.settings.MinimumPasswordLength) | ||||
| 			if err != nil { | ||||
| 				return http.StatusInternalServerError, err | ||||
| 				return http.StatusBadRequest, err | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,26 @@ | |||
| package users | ||||
| 
 | ||||
| import ( | ||||
| 	"embed" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| //go:embed assets
 | ||||
| var assets embed.FS | ||||
| var commonPasswords map[string]struct{} | ||||
| 
 | ||||
| //nolint:gochecknoinits
 | ||||
| func init() { | ||||
| 	// Password list sourced from:
 | ||||
| 	// https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/100k-most-used-passwords-NCSC.txt
 | ||||
| 	data, err := assets.ReadFile("assets/common-passwords.txt") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	passwords := strings.Split(strings.TrimSpace(string(data)), "\n") | ||||
| 	commonPasswords = make(map[string]struct{}, len(passwords)) | ||||
| 	for _, password := range passwords { | ||||
| 		commonPasswords[strings.TrimSpace(password)] = struct{}{} | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -9,10 +9,14 @@ import ( | |||
| 	fbErrors "github.com/filebrowser/filebrowser/v2/errors" | ||||
| ) | ||||
| 
 | ||||
| // HashPwd hashes a password.
 | ||||
| func HashAndValidatePwd(password string, minimumLength uint) (string, error) { | ||||
| // ValidateAndHashPwd validates and hashes a password.
 | ||||
| func ValidateAndHashPwd(password string, minimumLength uint) (string, error) { | ||||
| 	if uint(len(password)) < minimumLength { | ||||
| 		return "", fbErrors.ErrShortPassword | ||||
| 		return "", fbErrors.ErrShortPassword{MinimumLength: minimumLength} | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := commonPasswords[password]; ok { | ||||
| 		return "", fbErrors.ErrEasyPassword | ||||
| 	} | ||||
| 
 | ||||
| 	return HashPwd(password) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Henrique Dias
						Henrique Dias