added support for verifying sha256/sha512 passwords hash
this simplifies the migration of users from some proprietary products Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
48939b2b4f
commit
74e5999c63
3 changed files with 32 additions and 9 deletions
|
@ -585,7 +585,9 @@ Supported hash algorithms:
|
|||
- MD5 crypt APR1, prefix `$apr1$`
|
||||
- SHA256 crypt, prefix `$5$`
|
||||
- SHA512 crypt, prefix `$6$`
|
||||
- LDAP MD5, prefix `{MD5}`
|
||||
- MD5 digest, prefix `{MD5}`
|
||||
- SHA256 digest, prefix `{SHA256}`
|
||||
- SHA512 digest, prefix `{SHA512}`
|
||||
|
||||
If you set a password with one of these prefixes it will not be hashed.
|
||||
When users log in, if their passwords are stored with anything other than the preferred algorithm, SFTPGo will automatically upgrade the algorithm to the preferred one.
|
||||
|
|
|
@ -100,7 +100,9 @@ const (
|
|||
sha256cryptPwdPrefix = "$5$"
|
||||
sha512cryptPwdPrefix = "$6$"
|
||||
yescryptPwdPrefix = "$y$"
|
||||
md5LDAPPwdPrefix = "{MD5}"
|
||||
md5DigestPwdPrefix = "{MD5}"
|
||||
sha256DigestPwdPrefix = "{SHA256}"
|
||||
sha512DigestPwdPrefix = "{SHA512}"
|
||||
trackQuotaDisabledError = "please enable track_quota in your configuration to use this method"
|
||||
operationAdd = "add"
|
||||
operationUpdate = "update"
|
||||
|
@ -180,12 +182,13 @@ var (
|
|||
sqlPlaceholders []string
|
||||
internalHashPwdPrefixes = []string{argonPwdPrefix, bcryptPwdPrefix}
|
||||
hashPwdPrefixes = []string{argonPwdPrefix, bcryptPwdPrefix, pbkdf2SHA1Prefix, pbkdf2SHA256Prefix,
|
||||
pbkdf2SHA512Prefix, pbkdf2SHA256B64SaltPrefix, md5cryptPwdPrefix, md5cryptApr1PwdPrefix, md5LDAPPwdPrefix,
|
||||
sha256cryptPwdPrefix, sha512cryptPwdPrefix, yescryptPwdPrefix}
|
||||
pbkdf2SHA512Prefix, pbkdf2SHA256B64SaltPrefix, md5cryptPwdPrefix, md5cryptApr1PwdPrefix, md5DigestPwdPrefix,
|
||||
sha256DigestPwdPrefix, sha512DigestPwdPrefix, sha256cryptPwdPrefix, sha512cryptPwdPrefix, yescryptPwdPrefix}
|
||||
pbkdfPwdPrefixes = []string{pbkdf2SHA1Prefix, pbkdf2SHA256Prefix, pbkdf2SHA512Prefix, pbkdf2SHA256B64SaltPrefix}
|
||||
pbkdfPwdB64SaltPrefixes = []string{pbkdf2SHA256B64SaltPrefix}
|
||||
unixPwdPrefixes = []string{md5cryptPwdPrefix, md5cryptApr1PwdPrefix, sha256cryptPwdPrefix, sha512cryptPwdPrefix,
|
||||
yescryptPwdPrefix}
|
||||
digestPwdPrefixes = []string{md5DigestPwdPrefix, sha256DigestPwdPrefix, sha512DigestPwdPrefix}
|
||||
sharedProviders = []string{PGSQLDataProviderName, MySQLDataProviderName, CockroachDataProviderName}
|
||||
logSender = "dataprovider"
|
||||
sqlTableUsers string
|
||||
|
@ -3211,10 +3214,8 @@ func isPasswordOK(user *User, password string) (bool, error) {
|
|||
if err != nil {
|
||||
return match, err
|
||||
}
|
||||
} else if strings.HasPrefix(user.Password, md5LDAPPwdPrefix) {
|
||||
h := md5.New()
|
||||
h.Write([]byte(password))
|
||||
match = fmt.Sprintf("%s%x", md5LDAPPwdPrefix, h.Sum(nil)) == user.Password
|
||||
} else if util.IsStringPrefixInSlice(user.Password, digestPwdPrefixes) {
|
||||
match = compareDigestPasswordAndHash(user, password)
|
||||
}
|
||||
if err == nil && match {
|
||||
cachedUserPasswords.Add(user.Username, password, user.Password)
|
||||
|
@ -3377,6 +3378,25 @@ func checkUserAndPubKey(user *User, pubKey []byte, isSSHCert bool) (User, string
|
|||
return *user, "", ErrInvalidCredentials
|
||||
}
|
||||
|
||||
func compareDigestPasswordAndHash(user *User, password string) bool {
|
||||
if strings.HasPrefix(user.Password, md5DigestPwdPrefix) {
|
||||
h := md5.New()
|
||||
h.Write([]byte(password))
|
||||
return fmt.Sprintf("%s%x", md5DigestPwdPrefix, h.Sum(nil)) == user.Password
|
||||
}
|
||||
if strings.HasPrefix(user.Password, sha256DigestPwdPrefix) {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(password))
|
||||
return fmt.Sprintf("%s%x", sha256DigestPwdPrefix, h.Sum(nil)) == user.Password
|
||||
}
|
||||
if strings.HasPrefix(user.Password, sha512DigestPwdPrefix) {
|
||||
h := sha512.New()
|
||||
h.Write([]byte(password))
|
||||
return fmt.Sprintf("%s%x", sha512DigestPwdPrefix, h.Sum(nil)) == user.Password
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func compareUnixPasswordAndHash(user *User, password string) (bool, error) {
|
||||
if strings.HasPrefix(user.Password, yescryptPwdPrefix) {
|
||||
return compareYescryptPassword(user.Password, password)
|
||||
|
|
|
@ -7416,7 +7416,8 @@ func TestHashedPasswords(t *testing.T) {
|
|||
pwdMapping["$5$h4Aalt0fJdGX8sgv$Rd2ew0fvgzUN.DzAVlKa9QL4q/DZWo4SsKpB9.3AyZ/"] = plainPwd
|
||||
pwdMapping["$apr1$OBWLeSme$WoJbB736e7kKxMBIAqilb1"] = plainPwd
|
||||
pwdMapping["{MD5}5f4dcc3b5aa765d61d8327deb882cf99"] = plainPwd
|
||||
|
||||
pwdMapping["{SHA256}5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"] = plainPwd
|
||||
pwdMapping["{SHA512}b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86"] = plainPwd
|
||||
for pwd, clearPwd := range pwdMapping {
|
||||
u := getTestUser(usePubKey)
|
||||
u.Password = pwd
|
||||
|
|
Loading…
Reference in a new issue