mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-04-23 20:49:13 -05:00
Added an option to enable a password check against a Banned-Password List (#7315)
* Added an option to enable a password check against a Banned-Password-List * Update services/frontend/README.md Co-authored-by: Martin <github@diemattels.at> Co-authored-by: Edith Parzefall <edith_parzefall@gmx.de> --------- Co-authored-by: Roman Perekhod <rperekhod@owncloud.com> Co-authored-by: Martin <github@diemattels.at> Co-authored-by: Edith Parzefall <edith_parzefall@gmx.de>
This commit is contained in:
+26
-23
@@ -172,32 +172,35 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if tfRes.Status.Code != rpc.Code_CODE_OK {
|
||||
if tfRes.Status.Code == rpc.Code_CODE_OK {
|
||||
sRes, err := client.Stat(ctx, &provider.StatRequest{
|
||||
Ref: ref,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error sending grpc touch file request")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if sRes.Status.Code != rpc.Code_CODE_OK {
|
||||
log.Error().Interface("status", sRes.Status).Msg("error touching file")
|
||||
errors.HandleErrorStatus(&log, w, sRes.Status)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set(net.HeaderETag, sRes.Info.Etag)
|
||||
w.Header().Set(net.HeaderOCETag, sRes.Info.Etag)
|
||||
w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*sRes.Info.Id))
|
||||
w.Header().Set(net.HeaderLastModified, net.RFC1123Z(sRes.Info.Mtime))
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
return
|
||||
}
|
||||
|
||||
if tfRes.Status.Code != rpc.Code_CODE_ALREADY_EXISTS {
|
||||
log.Error().Interface("status", tfRes.Status).Msg("error touching file")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
errors.HandleErrorStatus(&log, w, tfRes.Status)
|
||||
return
|
||||
}
|
||||
sRes, err := client.Stat(ctx, &provider.StatRequest{
|
||||
Ref: ref,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error sending grpc touch file request")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if sRes.Status.Code != rpc.Code_CODE_OK {
|
||||
log.Error().Interface("status", sRes.Status).Msg("error touching file")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set(net.HeaderETag, sRes.Info.Etag)
|
||||
w.Header().Set(net.HeaderOCETag, sRes.Info.Etag)
|
||||
w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*sRes.Info.Id))
|
||||
w.Header().Set(net.HeaderLastModified, net.RFC1123Z(sRes.Info.Mtime))
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
return
|
||||
}
|
||||
|
||||
utils.AppendPlainToOpaque(opaque, net.HeaderUploadLength, strconv.FormatInt(length, 10))
|
||||
|
||||
Generated
Vendored
+7
-6
@@ -88,12 +88,13 @@ type CapabilitiesGraph struct {
|
||||
|
||||
// CapabilitiesPasswordPolicy hold the password policy capabilities
|
||||
type CapabilitiesPasswordPolicy struct {
|
||||
MinCharacters int `json:"min_characters" xml:"min_characters" mapstructure:"min_characters"`
|
||||
MaxCharacters int `json:"max_characters" xml:"max_characters" mapstructure:"max_characters"`
|
||||
MinLowerCaseCharacters int `json:"min_lowercase_characters" xml:"min_lowercase_characters" mapstructure:"min_lowercase_characters"`
|
||||
MinUpperCaseCharacters int `json:"min_uppercase_characters" xml:"min_uppercase_characters" mapstructure:"min_uppercase_characters"`
|
||||
MinDigits int `json:"min_digits" xml:"min_digits" mapstructure:"min_digits"`
|
||||
MinSpecialCharacters int `json:"min_special_characters" xml:"min_special_characters" mapstructure:"min_special_characters"`
|
||||
MinCharacters int `json:"min_characters" xml:"min_characters" mapstructure:"min_characters"`
|
||||
MaxCharacters int `json:"max_characters" xml:"max_characters" mapstructure:"max_characters"`
|
||||
MinLowerCaseCharacters int `json:"min_lowercase_characters" xml:"min_lowercase_characters" mapstructure:"min_lowercase_characters"`
|
||||
MinUpperCaseCharacters int `json:"min_uppercase_characters" xml:"min_uppercase_characters" mapstructure:"min_uppercase_characters"`
|
||||
MinDigits int `json:"min_digits" xml:"min_digits" mapstructure:"min_digits"`
|
||||
MinSpecialCharacters int `json:"min_special_characters" xml:"min_special_characters" mapstructure:"min_special_characters"`
|
||||
BannedPasswordsList map[string]struct{} `json:"-" xml:"-" mapstructure:"banned_passwords_list"`
|
||||
}
|
||||
|
||||
// CapabilitiesGraphUsers holds the graph user capabilities
|
||||
|
||||
Generated
Vendored
+2
-2
@@ -153,7 +153,7 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request,
|
||||
if err := h.passwordValidator.Validate(password); err != nil {
|
||||
return nil, &ocsError{
|
||||
Code: response.MetaBadRequest.StatusCode,
|
||||
Message: "password validation failed",
|
||||
Message: err.Error(),
|
||||
Error: fmt.Errorf("password validation failed: %w", err),
|
||||
}
|
||||
}
|
||||
@@ -479,7 +479,7 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar
|
||||
// skip validation if the clear password scenario
|
||||
if len(newPassword[0]) > 0 {
|
||||
if err := h.passwordValidator.Validate(newPassword[0]); err != nil {
|
||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, fmt.Errorf("missing required password %w", err).Error(), err)
|
||||
response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, err.Error(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Generated
Vendored
+2
-1
@@ -1592,7 +1592,7 @@ func publicPwdEnforced(c *config.Config) passwordEnforced {
|
||||
|
||||
func passwordPolicies(c *config.Config) password.Validator {
|
||||
if c.Capabilities.Capabilities == nil || c.Capabilities.Capabilities.PasswordPolicy == nil {
|
||||
return password.NewPasswordPolicy(0, 0, 0, 0, 0)
|
||||
return password.NewPasswordPolicy(0, 0, 0, 0, 0, nil)
|
||||
}
|
||||
return password.NewPasswordPolicy(
|
||||
c.Capabilities.Capabilities.PasswordPolicy.MinCharacters,
|
||||
@@ -1600,6 +1600,7 @@ func passwordPolicies(c *config.Config) password.Validator {
|
||||
c.Capabilities.Capabilities.PasswordPolicy.MinUpperCaseCharacters,
|
||||
c.Capabilities.Capabilities.PasswordPolicy.MinDigits,
|
||||
c.Capabilities.Capabilities.PasswordPolicy.MinSpecialCharacters,
|
||||
c.Capabilities.Capabilities.PasswordPolicy.BannedPasswordsList,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -23,18 +23,20 @@ type Policies struct {
|
||||
minUpperCaseCharacters int
|
||||
minDigits int
|
||||
minSpecialCharacters int
|
||||
bannedPasswordsList map[string]struct{}
|
||||
digitsRegexp *regexp.Regexp
|
||||
specialCharactersRegexp *regexp.Regexp
|
||||
}
|
||||
|
||||
// NewPasswordPolicy returns a new NewPasswordPolicy instance
|
||||
func NewPasswordPolicy(minCharacters, minLowerCaseCharacters, minUpperCaseCharacters, minDigits, minSpecialCharacters int) Validator {
|
||||
func NewPasswordPolicy(minCharacters, minLowerCaseCharacters, minUpperCaseCharacters, minDigits, minSpecialCharacters int, bannedPasswordsList map[string]struct{}) Validator {
|
||||
p := &Policies{
|
||||
minCharacters: minCharacters,
|
||||
minLowerCaseCharacters: minLowerCaseCharacters,
|
||||
minUpperCaseCharacters: minUpperCaseCharacters,
|
||||
minDigits: minDigits,
|
||||
minSpecialCharacters: minSpecialCharacters,
|
||||
bannedPasswordsList: bannedPasswordsList,
|
||||
}
|
||||
|
||||
p.digitsRegexp = regexp.MustCompile("[0-9]")
|
||||
@@ -48,7 +50,11 @@ func (s Policies) Validate(str string) error {
|
||||
if !utf8.ValidString(str) {
|
||||
return fmt.Errorf("the password contains invalid characters")
|
||||
}
|
||||
err := s.validateCharacters(str)
|
||||
err := s.validateBannedList(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.validateCharacters(str)
|
||||
if err != nil {
|
||||
allErr = errors.Join(allErr, err)
|
||||
}
|
||||
@@ -74,6 +80,16 @@ func (s Policies) Validate(str string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Policies) validateBannedList(str string) error {
|
||||
if len(s.bannedPasswordsList) == 0 {
|
||||
return nil
|
||||
}
|
||||
if _, ok := s.bannedPasswordsList[str]; ok {
|
||||
return fmt.Errorf("unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Policies) validateCharacters(str string) error {
|
||||
if s.count(str) < s.minCharacters {
|
||||
return fmt.Errorf("at least %d characters are required", s.minCharacters)
|
||||
@@ -104,7 +120,7 @@ func (s Policies) validateDigits(str string) error {
|
||||
|
||||
func (s Policies) validateSpecialCharacters(str string) error {
|
||||
if s.countSpecialCharacters(str) < s.minSpecialCharacters {
|
||||
return fmt.Errorf("at least %d special characters are required. %s", s.minSpecialCharacters, _defaultSpecialCharacters)
|
||||
return fmt.Errorf("at least %d special characters are required %s", s.minSpecialCharacters, _defaultSpecialCharacters)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user