mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 02:57:59 +00:00
Return errInvalidCredentials when wrong credentials is provided for existent users (#17104)
* adding errInvalidCredentials * fixing tests * add changelog * fixing fmt errors * test if routeErr is seen externally and fixing error comment * adding fmt changes * adding comments
This commit is contained in:
@@ -174,7 +174,7 @@ func TestAppRole_RoleNameCaseSensitivity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Storage: s,
|
Storage: s,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
@@ -233,7 +233,7 @@ func TestAppRole_RoleNameCaseSensitivity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Storage: s,
|
Storage: s,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
@@ -292,7 +292,7 @@ func TestAppRole_RoleNameCaseSensitivity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Storage: s,
|
Storage: s,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
@@ -351,7 +351,7 @@ func TestAppRole_RoleNameCaseSensitivity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Storage: s,
|
Storage: s,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
@@ -410,7 +410,7 @@ func TestAppRole_RoleNameCaseSensitivity(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Storage: s,
|
Storage: s,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ func (b *backend) pathLoginUpdate(ctx context.Context, req *logical.Request, dat
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
return logical.ErrorResponse("invalid secret id"), nil
|
return logical.ErrorResponse("invalid secret id"), logical.ErrInvalidCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a secret ID entry does not have a corresponding accessor
|
// If a secret ID entry does not have a corresponding accessor
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ func TestAppRole_RoleNameLowerCasing(t *testing.T) {
|
|||||||
"secret_id": secretID,
|
"secret_id": secretID,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil && err != logical.ErrInvalidCredentials {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if resp == nil || !resp.IsError() {
|
if resp == nil || !resp.IsError() {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
|
|||||||
if b.Logger().IsDebug() {
|
if b.Logger().IsDebug() {
|
||||||
b.Logger().Debug("ldap bind failed", "error", err)
|
b.Logger().Debug("ldap bind failed", "error", err)
|
||||||
}
|
}
|
||||||
return "", nil, logical.ErrorResponse(errUserBindFailed), nil, nil
|
return "", nil, logical.ErrorResponse(errUserBindFailed), nil, logical.ErrInvalidCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
// We re-bind to the BindDN if it's defined because we assume
|
// We re-bind to the BindDN if it's defined because we assume
|
||||||
@@ -117,7 +117,7 @@ func (b *backend) Login(ctx context.Context, req *logical.Request, username stri
|
|||||||
if b.Logger().IsDebug() {
|
if b.Logger().IsDebug() {
|
||||||
b.Logger().Debug("error while attempting to re-bind with the BindDN User", "error", err)
|
b.Logger().Debug("error while attempting to re-bind with the BindDN User", "error", err)
|
||||||
}
|
}
|
||||||
return "", nil, logical.ErrorResponse("ldap operation failed: failed to re-bind with the BindDN user"), nil, nil
|
return "", nil, logical.ErrorResponse("ldap operation failed: failed to re-bind with the BindDN user"), nil, logical.ErrInvalidCredentials
|
||||||
}
|
}
|
||||||
if b.Logger().IsDebug() {
|
if b.Logger().IsDebug() {
|
||||||
b.Logger().Debug("re-bound to original binddn")
|
b.Logger().Debug("re-bound to original binddn")
|
||||||
|
|||||||
@@ -86,14 +86,26 @@ func (b *backend) pathLogin(ctx context.Context, req *logical.Request, d *framew
|
|||||||
// Check for a password match. Check for a hash collision for Vault 0.2+,
|
// Check for a password match. Check for a hash collision for Vault 0.2+,
|
||||||
// but handle the older legacy passwords with a constant time comparison.
|
// but handle the older legacy passwords with a constant time comparison.
|
||||||
passwordBytes := []byte(password)
|
passwordBytes := []byte(password)
|
||||||
if !legacyPassword {
|
switch {
|
||||||
|
case !legacyPassword:
|
||||||
if err := bcrypt.CompareHashAndPassword(userPassword, passwordBytes); err != nil {
|
if err := bcrypt.CompareHashAndPassword(userPassword, passwordBytes); err != nil {
|
||||||
|
// The failed login info of existing users alone are tracked as only
|
||||||
|
// existing user's failed login information is stored in storage for optimization
|
||||||
|
if user == nil || userError != nil {
|
||||||
return logical.ErrorResponse("invalid username or password"), nil
|
return logical.ErrorResponse("invalid username or password"), nil
|
||||||
}
|
}
|
||||||
} else {
|
return logical.ErrorResponse("invalid username or password"), logical.ErrInvalidCredentials
|
||||||
|
}
|
||||||
|
default:
|
||||||
if subtle.ConstantTimeCompare(userPassword, passwordBytes) != 1 {
|
if subtle.ConstantTimeCompare(userPassword, passwordBytes) != 1 {
|
||||||
|
// The failed login info of existing users alone are tracked as only
|
||||||
|
// existing user's failed login information is stored in storage for optimization
|
||||||
|
if user == nil || userError != nil {
|
||||||
return logical.ErrorResponse("invalid username or password"), nil
|
return logical.ErrorResponse("invalid username or password"), nil
|
||||||
}
|
}
|
||||||
|
return logical.ErrorResponse("invalid username or password"), logical.ErrInvalidCredentials
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if userError != nil {
|
if userError != nil {
|
||||||
|
|||||||
4
changelog/17104.txt
Normal file
4
changelog/17104.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
```release-note:change
|
||||||
|
auth: Returns invalid credentials for ldap, userpass and approle when wrong credentials are provided for existent users.
|
||||||
|
This will only be used internally for implementing user lockout.
|
||||||
|
```
|
||||||
@@ -17,6 +17,11 @@ var (
|
|||||||
// ErrPermissionDenied is returned if the client is not authorized
|
// ErrPermissionDenied is returned if the client is not authorized
|
||||||
ErrPermissionDenied = errors.New("permission denied")
|
ErrPermissionDenied = errors.New("permission denied")
|
||||||
|
|
||||||
|
// ErrInvalidCredentials is returned when the provided credentials are incorrect
|
||||||
|
// This is used internally for user lockout purposes. This is not seen externally.
|
||||||
|
// The status code returned does not change because of this error
|
||||||
|
ErrInvalidCredentials = errors.New("invalid credentials")
|
||||||
|
|
||||||
// ErrMultiAuthzPending is returned if the the request needs more
|
// ErrMultiAuthzPending is returned if the the request needs more
|
||||||
// authorizations
|
// authorizations
|
||||||
ErrMultiAuthzPending = errors.New("request needs further approval")
|
ErrMultiAuthzPending = errors.New("request needs further approval")
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ func RespondErrorCommon(req *Request, resp *Response, err error) (int, error) {
|
|||||||
statusCode = http.StatusNotFound
|
statusCode = http.StatusNotFound
|
||||||
case errwrap.Contains(err, ErrRelativePath.Error()):
|
case errwrap.Contains(err, ErrRelativePath.Error()):
|
||||||
statusCode = http.StatusBadRequest
|
statusCode = http.StatusBadRequest
|
||||||
|
case errwrap.Contains(err, ErrInvalidCredentials.Error()):
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package logical
|
package logical
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -60,6 +61,17 @@ func TestResponseUtil_RespondErrorCommon_basic(t *testing.T) {
|
|||||||
respErr: nil,
|
respErr: nil,
|
||||||
expectedStatus: 0,
|
expectedStatus: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Invalid Credentials error ",
|
||||||
|
respErr: ErrInvalidCredentials,
|
||||||
|
resp: &Response{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"error": "error due to wrong credentials",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedErr: errors.New("error due to wrong credentials"),
|
||||||
|
expectedStatus: 400,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|||||||
Reference in New Issue
Block a user