Password Complexity Checks  (#6230)
	
		
	
				
					
				
			Add password complexity checks. The default settings require a lowercase, uppercase, number and a special character within passwords. Co-Authored-By: T-M-A <maxim.tkachenko@gmail.com> Co-Authored-By: Lanre Adelowo <adelowomailbox@gmail.com> Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-Authored-By: Lauris BH <lauris@nix.lv>tokarchuk/v1.17
							parent
							
								
									f9aba9ba0f
								
							
						
					
					
						commit
						db657192d0
					
				@ -0,0 +1,73 @@ | 
				
			||||
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||
// Use of this source code is governed by a MIT-style
 | 
				
			||||
// license that can be found in the LICENSE file.
 | 
				
			||||
 | 
				
			||||
package password | 
				
			||||
 | 
				
			||||
import ( | 
				
			||||
	"crypto/rand" | 
				
			||||
	"math/big" | 
				
			||||
	"regexp" | 
				
			||||
	"sync" | 
				
			||||
 | 
				
			||||
	"code.gitea.io/gitea/modules/setting" | 
				
			||||
) | 
				
			||||
 | 
				
			||||
var matchComplexities = map[string]regexp.Regexp{} | 
				
			||||
var matchComplexityOnce sync.Once | 
				
			||||
var validChars string | 
				
			||||
var validComplexities = map[string]string{ | 
				
			||||
	"lower": "abcdefghijklmnopqrstuvwxyz", | 
				
			||||
	"upper": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", | 
				
			||||
	"digit": "0123456789", | 
				
			||||
	"spec":  `][ !"#$%&'()*+,./:;<=>?@\^_{|}~` + "`-", | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// NewComplexity for preparation
 | 
				
			||||
func NewComplexity() { | 
				
			||||
	matchComplexityOnce.Do(func() { | 
				
			||||
		if len(setting.PasswordComplexity) > 0 { | 
				
			||||
			for key, val := range setting.PasswordComplexity { | 
				
			||||
				matchComplexity := regexp.MustCompile(val) | 
				
			||||
				matchComplexities[key] = *matchComplexity | 
				
			||||
				validChars += validComplexities[key] | 
				
			||||
			} | 
				
			||||
		} else { | 
				
			||||
			for _, val := range validComplexities { | 
				
			||||
				validChars += val | 
				
			||||
			} | 
				
			||||
		} | 
				
			||||
	}) | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// IsComplexEnough return True if password is Complexity
 | 
				
			||||
func IsComplexEnough(pwd string) bool { | 
				
			||||
	if len(setting.PasswordComplexity) > 0 { | 
				
			||||
		NewComplexity() | 
				
			||||
		for _, val := range matchComplexities { | 
				
			||||
			if !val.MatchString(pwd) { | 
				
			||||
				return false | 
				
			||||
			} | 
				
			||||
		} | 
				
			||||
	} | 
				
			||||
	return true | 
				
			||||
} | 
				
			||||
 | 
				
			||||
// Generate  a random password
 | 
				
			||||
func Generate(n int) (string, error) { | 
				
			||||
	NewComplexity() | 
				
			||||
	buffer := make([]byte, n) | 
				
			||||
	max := big.NewInt(int64(len(validChars))) | 
				
			||||
	for { | 
				
			||||
		for j := 0; j < n; j++ { | 
				
			||||
			rnd, err := rand.Int(rand.Reader, max) | 
				
			||||
			if err != nil { | 
				
			||||
				return "", err | 
				
			||||
			} | 
				
			||||
			buffer[j] = validChars[rnd.Int64()] | 
				
			||||
		} | 
				
			||||
		if IsComplexEnough(string(buffer)) && string(buffer[0]) != " " && string(buffer[n-1]) != " " { | 
				
			||||
			return string(buffer), nil | 
				
			||||
		} | 
				
			||||
	} | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue