Merge branch 'cassandra-3.11' into trunk
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/f40198fc Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/f40198fc Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/f40198fc Branch: refs/heads/trunk Commit: f40198fc685028f87c26be4c51b2352e3cc01262 Parents: c84269a 4f12c40 Author: Jeff Jirsa <[email protected]> Authored: Wed Aug 30 21:59:43 2017 -0700 Committer: Jeff Jirsa <[email protected]> Committed: Wed Aug 30 22:02:07 2017 -0700 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/auth/PasswordAuthenticator.java | 16 ++++- .../auth/PasswordAuthenticatorTest.java | 64 ++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f40198fc/CHANGES.txt ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/f40198fc/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/auth/PasswordAuthenticator.java index b82b0ad,54f7985..b1604e7 --- a/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java +++ b/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java @@@ -75,36 -82,97 +75,50 @@@ public class PasswordAuthenticator impl return true; } + protected static boolean checkpw(String password, String hash) + { + try + { + return BCrypt.checkpw(password, hash); + } + catch (Exception e) + { + // Improperly formatted hashes may cause BCrypt.checkpw to throw, so trap any other exception as a failure + logger.warn("Error: invalid password hash encountered, rejecting user", e); + return false; + } + } + private AuthenticatedUser authenticate(String username, String password) throws AuthenticationException { - try - { - String hash = cache.get(username); - if (!checkpw(password, hash)) - throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); - - return new AuthenticatedUser(username); - } - catch (ExecutionException | UncheckedExecutionException e) - { - // the credentials were somehow invalid - either a non-existent role, or one without a defined password - if (e.getCause() instanceof NoSuchCredentialsException) - throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); - - // an unanticipated exception occured whilst querying the credentials table - if (e.getCause() instanceof RequestExecutionException) - { - logger.trace("Error performing internal authentication", e); - throw new AuthenticationException(String.format("Error during authentication of user %s : %s", username, e.getMessage())); - } - - throw new RuntimeException(e); - } - } - - private String queryHashedPassword(String username) throws NoSuchCredentialsException - { - try - { - SelectStatement authenticationStatement = authenticationStatement(); - - ResultMessage.Rows rows = - authenticationStatement.execute(QueryState.forInternalCalls(), - QueryOptions.forInternalCalls(consistencyForRole(username), - Lists.newArrayList(ByteBufferUtil.bytes(username))), - System.nanoTime()); + String hash = cache.get(username); - if (!BCrypt.checkpw(password, hash)) ++ if (!checkpw(password, hash)) + throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); - // If either a non-existent role name was supplied, or no credentials - // were found for that role we don't want to cache the result so we throw - // a specific, but unchecked, exception to keep LoadingCache happy. - if (rows.result.isEmpty()) - throw new NoSuchCredentialsException(); - - UntypedResultSet result = UntypedResultSet.create(rows.result); - if (!result.one().has(SALTED_HASH)) - throw new NoSuchCredentialsException(); - - return result.one().getString(SALTED_HASH); - } - catch (RequestExecutionException e) - { - logger.trace("Error performing internal authentication", e); - throw e; - } + return new AuthenticatedUser(username); } - /** - * If the legacy users table exists try to verify credentials there. This is to handle the case - * where the cluster is being upgraded and so is running with mixed versions of the authn tables - */ - private SelectStatement authenticationStatement() + private String queryHashedPassword(String username) { - if (Schema.instance.getCFMetaData(SchemaConstants.AUTH_KEYSPACE_NAME, LEGACY_CREDENTIALS_TABLE) == null) - return authenticateStatement; - else - { - // the statement got prepared, we to try preparing it again. - // If the credentials was initialised only after statement got prepared, re-prepare (CASSANDRA-12813). - if (legacyAuthenticateStatement == null) - prepareLegacyAuthenticateStatement(); - return legacyAuthenticateStatement; - } + ResultMessage.Rows rows = + authenticateStatement.execute(QueryState.forInternalCalls(), + QueryOptions.forInternalCalls(consistencyForRole(username), + Lists.newArrayList(ByteBufferUtil.bytes(username))), + System.nanoTime()); + + // If either a non-existent role name was supplied, or no credentials + // were found for that role we don't want to cache the result so we throw + // a specific, but unchecked, exception to keep LoadingCache happy. + if (rows.result.isEmpty()) + throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); + + UntypedResultSet result = UntypedResultSet.create(rows.result); + if (!result.one().has(SALTED_HASH)) + throw new AuthenticationException(String.format("Provided username %s and/or password are incorrect", username)); + + return result.one().getString(SALTED_HASH); } - public Set<DataResource> protectedResources() { // Also protected by CassandraRoleManager, but the duplication doesn't hurt and is more explicit --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
