You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jj...@apache.org on 2017/08/31 05:05:01 UTC
[2/6] cassandra git commit: Better tolerate improperly formatted
bcrypt hashes
Better tolerate improperly formatted bcrypt hashes
Patch by Jeff Jirsa; Reviewed by Sam Tunnicliffe for CASSANDRA-13626
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/5e7f60f6
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/5e7f60f6
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/5e7f60f6
Branch: refs/heads/cassandra-3.11
Commit: 5e7f60f6bf5da386076faa08cefb3970a6ba5cc0
Parents: ded6636
Author: Jeff Jirsa <jj...@apple.com>
Authored: Tue Aug 29 15:21:08 2017 -0700
Committer: Jeff Jirsa <jj...@apple.com>
Committed: Wed Aug 30 21:58:26 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/5e7f60f6/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index aca9e1f..b405fdf 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.0.15
+ * Better tolerate improperly formatted bcrypt hashes (CASSANDRA-13626)
* Fix race condition in read command serialization (CASSANDRA-13363)
* Enable segement creation before recovering commitlogs (CASSANDRA-13587)
* Fix AssertionError in short read protection (CASSANDRA-13747)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e7f60f6/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java b/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java
index ca610d1..58f61f5 100644
--- a/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/PasswordAuthenticator.java
@@ -74,6 +74,20 @@ public class PasswordAuthenticator implements IAuthenticator
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
@@ -162,7 +176,7 @@ public class PasswordAuthenticator implements IAuthenticator
Lists.newArrayList(ByteBufferUtil.bytes(username))));
UntypedResultSet result = UntypedResultSet.create(rows.result);
- if ((result.isEmpty() || !result.one().has(SALTED_HASH)) || !BCrypt.checkpw(password, result.one().getString(SALTED_HASH)))
+ if ((result.isEmpty() || !result.one().has(SALTED_HASH)) || !checkpw(password, result.one().getString(SALTED_HASH)))
throw new AuthenticationException("Username and/or password are incorrect");
return new AuthenticatedUser(username);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/5e7f60f6/test/unit/org/apache/cassandra/auth/PasswordAuthenticatorTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/auth/PasswordAuthenticatorTest.java b/test/unit/org/apache/cassandra/auth/PasswordAuthenticatorTest.java
new file mode 100644
index 0000000..37763d7
--- /dev/null
+++ b/test/unit/org/apache/cassandra/auth/PasswordAuthenticatorTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.auth;
+
+
+import org.junit.Test;
+
+import static org.apache.cassandra.auth.CassandraRoleManager.*;
+import static org.apache.cassandra.auth.PasswordAuthenticator.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mindrot.jbcrypt.BCrypt.hashpw;
+import static org.mindrot.jbcrypt.BCrypt.gensalt;
+
+public class PasswordAuthenticatorTest
+{
+ @Test
+ public void testCheckpw() throws Exception
+ {
+ // Valid and correct
+ assertTrue(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw(DEFAULT_SUPERUSER_PASSWORD, gensalt(getGensaltLogRounds()))));
+ assertTrue(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw(DEFAULT_SUPERUSER_PASSWORD, gensalt(4))));
+ assertTrue(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw(DEFAULT_SUPERUSER_PASSWORD, gensalt(31))));
+
+ // Valid but incorrect hashes
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw("incorrect0", gensalt(4))));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw("incorrect1", gensalt(10))));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, hashpw("incorrect2", gensalt(31))));
+
+ // Invalid hash values, the jBCrypt library implementation
+ // throws an exception which we catch and treat as a failure
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, ""));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "0"));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"));
+
+ // Format is structurally right, but actually invalid
+ // bad salt version
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$5x$10$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ // invalid number of rounds, multiple salt versions but it's the rounds that are incorrect
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2$02$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2a$02$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2$99$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2a$99$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ // unpadded rounds
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2$6$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ assertFalse(checkpw(DEFAULT_SUPERUSER_PASSWORD, "$2a$6$abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUVWXYZ01234"));
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org