Repository: commons-dbcp Updated Branches: refs/heads/master 064c81483 -> 3f28c60b2
[DBCP-502] org.apache.commons.dbcp2.datasources internals should use a char[] instead of a String to store passwords. Project: http://git-wip-us.apache.org/repos/asf/commons-dbcp/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-dbcp/commit/3f28c60b Tree: http://git-wip-us.apache.org/repos/asf/commons-dbcp/tree/3f28c60b Diff: http://git-wip-us.apache.org/repos/asf/commons-dbcp/diff/3f28c60b Branch: refs/heads/master Commit: 3f28c60b2ccbd4d3965eddfc2e652eb0027b10c9 Parents: 064c814 Author: Gary Gregory <garydgreg...@gmail.com> Authored: Sun Jun 10 13:05:00 2018 -0600 Committer: Gary Gregory <garydgreg...@gmail.com> Committed: Sun Jun 10 13:05:00 2018 -0600 ---------------------------------------------------------------------- src/changes/changes.xml | 3 + .../datasources/KeyedCPDSConnectionFactory.java | 2 +- .../datasources/PooledConnectionAndInfo.java | 37 +++++-- .../commons/dbcp2/datasources/UserPassKey.java | 110 ++++++++++++------- 4 files changed, 103 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/3f28c60b/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6fe260e..73e7933 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -94,6 +94,9 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="update" issue="DBCP-501" due-to="Gary Gregory"> org.apache.commons.dbcp2.datasources.CPDSConnectionFactory should use a char[] instead of a String to store passwords. </action> + <action dev="ggregory" type="update" issue="DBCP-502" due-to="Gary Gregory"> + org.apache.commons.dbcp2.datasources internals should use a char[] instead of a String to store passwords. + </action> </release> <release version="2.3.0" date="2018-05-12" description="This is a minor release, including bug fixes and enhancements."> <action dev="pschumacher" type="fix" issue="DBCP-476" due-to="Gary Evesson, Richard Cordova"> http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/3f28c60b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java index 98d8fab..160b78f 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/KeyedCPDSConnectionFactory.java @@ -336,7 +336,7 @@ class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory<UserPassKey @Override public void closePool(final String userName) throws SQLException { try { - pool.clear(new UserPassKey(userName, null)); + pool.clear(new UserPassKey(userName)); } catch (final Exception ex) { throw new SQLException("Error closing connection pool", ex); } http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/3f28c60b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java index 7f9bef8..3a0414d 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/PooledConnectionAndInfo.java @@ -19,6 +19,8 @@ package org.apache.commons.dbcp2.datasources; import javax.sql.PooledConnection; +import org.apache.commons.dbcp2.Utils; + /** * Immutable poolable object holding a PooledConnection along with the user name and password used to create the * connection. @@ -27,15 +29,26 @@ import javax.sql.PooledConnection; */ final class PooledConnectionAndInfo { private final PooledConnection pooledConnection; - private final String password; + private final char[] userPassword; private final String userName; - private final UserPassKey upkey; + private final UserPassKey upKey; - PooledConnectionAndInfo(final PooledConnection pc, final String userName, final String password) { + /** + * @since 2.4.0 + */ + PooledConnectionAndInfo(final PooledConnection pc, final String userName, final char[] userPassword) { this.pooledConnection = pc; this.userName = userName; - this.password = password; - upkey = new UserPassKey(userName, password); + this.userPassword = userPassword; + this.upKey = new UserPassKey(userName, userPassword); + } + + /** + * @deprecated Since 2.4.0 + */ + @Deprecated + PooledConnectionAndInfo(final PooledConnection pc, final String userName, final String userPassword) { + this(pc, userName, Utils.toCharArray(userPassword)); } PooledConnection getPooledConnection() { @@ -43,7 +56,7 @@ final class PooledConnectionAndInfo { } UserPassKey getUserPassKey() { - return upkey; + return upKey; } /** @@ -52,7 +65,17 @@ final class PooledConnectionAndInfo { * @return value of password. */ String getPassword() { - return password; + return Utils.toString(userPassword); + } + + /** + * Gets the value of password. + * + * @return value of password. + * @since 2.4.0 + */ + char[] getPasswordCharArray() { + return userPassword; } /** http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/3f28c60b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java index ee32bce..55b4a8f 100644 --- a/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java +++ b/src/main/java/org/apache/commons/dbcp2/datasources/UserPassKey.java @@ -19,87 +19,115 @@ package org.apache.commons.dbcp2.datasources; import java.io.Serializable; +import org.apache.commons.dbcp2.Utils; + /** - * <p>Holds a user name, password pair. Serves as a poolable object key for the KeyedObjectPool - * backing a SharedPoolDataSource. Two instances with the same user name are considered equal. - * This ensures that there will be only one keyed pool for each user in the pool. The password - * is used (along with the user name) by the KeyedCPDSConnectionFactory when creating new connections.</p> + * <p> + * Holds a user name and password pair. Serves as a poolable object key for the KeyedObjectPool backing a + * SharedPoolDataSource. Two instances with the same user name are considered equal. This ensures that there will be + * only one keyed pool for each user in the pool. The password is used (along with the user name) by the + * KeyedCPDSConnectionFactory when creating new connections. + * </p> * - * <p>{@link InstanceKeyDataSource#getConnection(String, String)} validates that the password used to create - * a connection matches the password provided by the client.</p> + * <p> + * {@link InstanceKeyDataSource#getConnection(String, String)} validates that the password used to create a connection + * matches the password provided by the client. + * </p> * * @since 2.0 */ class UserPassKey implements Serializable { private static final long serialVersionUID = 5142970911626584817L; - private final String password; private final String userName; - - UserPassKey(final String userName, final String password) { - this.userName = userName; - this.password = password; - } + private final char[] userPassword; /** - * Gets the value of password. - * - * @return value of password. + * @since 2.4.0 */ - public String getPassword() { - return password; + UserPassKey(final String userName) { + this(userName, (char[]) null); } /** - * Gets the value of user name. - * - * @return value of user name. + * @since 2.4.0 */ - public String getUsername() { - return userName; + UserPassKey(final String userName, final char[] password) { + this.userName = userName; + this.userPassword = password; + } + + UserPassKey(final String userName, final String userPassword) { + this(userName, Utils.toCharArray(userPassword)); } /** - * @return <code>true</code> if the user name fields for both - * objects are equal. Two instances with the same user name - * but different passwords are considered equal. - * - * @see java.lang.Object#equals(java.lang.Object) + * Only takes the user name into account. */ @Override - public boolean equals(final Object obj) { + public boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj == null) { return false; } - - if (obj == this) { - return true; + if (getClass() != obj.getClass()) { + return false; } - - if (!(obj instanceof UserPassKey)) { + UserPassKey other = (UserPassKey) obj; + if (userName == null) { + if (other.userName != null) { + return false; + } + } else if (!userName.equals(other.userName)) { return false; } + return true; + } - final UserPassKey key = (UserPassKey) obj; + /** + * Gets the value of password. + * + * @return value of password. + */ + public String getPassword() { + return Utils.toString(userPassword); + } + + /** + * Gets the value of password. + * + * @return value of password. + */ + public char[] getPasswordCharArray() { + return userPassword; + } - return this.userName == null ? - key.userName == null : - this.userName.equals(key.userName); + /** + * Gets the value of user name. + * + * @return value of user name. + */ + public String getUsername() { + return userName; } /** - * Returns the hash of the user name. + * Only takes the user name into account. */ @Override public int hashCode() { - return this.userName != null ? - this.userName.hashCode() : 0; + final int prime = 31; + int result = 1; + result = prime * result + ((userName == null) ? 0 : userName.hashCode()); + return result; } @Override public String toString() { final StringBuffer sb = new StringBuffer(50); sb.append("UserPassKey("); - sb.append(userName).append(", ").append(password).append(')'); + sb.append(userName).append(", ").append(userPassword).append(')'); return sb.toString(); } }