Commit bd4d07bc authored by Dave Cridland's avatar Dave Cridland Committed by GitHub

Merge pull request #671 from surevine/of-1104

OF-1104 Ensure SCRAM uses AuthProvider API
parents 2249ae78 121db7f2
......@@ -293,4 +293,17 @@ public class AuthFactory {
// TODO Auto-generated method stub
return authProvider.isScramSupported();
}
public static String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
return authProvider.getSalt(username);
}
public static int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
return authProvider.getIterations(username);
}
public static String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
return authProvider.getServerKey(username);
}
public static String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
return authProvider.getStoredKey(username);
}
}
\ No newline at end of file
......@@ -90,4 +90,8 @@ public interface AuthProvider {
public boolean supportsPasswordRetrieval();
boolean isScramSupported();
String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException;
int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException;
String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException;
String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException;
}
\ No newline at end of file
......@@ -55,7 +55,7 @@ public class DefaultAuthProvider implements AuthProvider {
private static final String LOAD_PASSWORD =
"SELECT plainPassword,encryptedPassword FROM ofUser WHERE username=?";
private static final String TEST_PASSWORD =
"SELECT plainPassword,encryptedPassword,iterations,salt,storedKey FROM ofUser WHERE username=?";
"SELECT plainPassword,encryptedPassword,iterations,salt,storedKey,serverKey FROM ofUser WHERE username=?";
private static final String UPDATE_PASSWORD =
"UPDATE ofUser SET plainPassword=?, encryptedPassword=?, storedKey=?, serverKey=?, salt=?, iterations=? WHERE username=?";
......@@ -68,6 +68,89 @@ public class DefaultAuthProvider implements AuthProvider {
}
private class UserInfo {
String plainText;
String encrypted;
int iterations;
String salt;
String storedKey;
String serverKey;
}
private UserInfo getUserInfo(String username) throws UnsupportedOperationException, UserNotFoundException {
if (!isScramSupported()) {
// Reject the operation since the provider does not support SCRAM
throw new UnsupportedOperationException();
}
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(TEST_PASSWORD);
pstmt.setString(1, username);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new UserNotFoundException(username);
}
UserInfo userInfo = new UserInfo();
userInfo.plainText = rs.getString(1);
userInfo.encrypted = rs.getString(2);
userInfo.iterations = rs.getInt(3);
userInfo.salt = rs.getString(4);
userInfo.storedKey = rs.getString(5);
userInfo.serverKey = rs.getString(6);
if (userInfo.encrypted != null) {
try {
userInfo.plainText = AuthFactory.decryptPassword(userInfo.encrypted);
}
catch (UnsupportedOperationException uoe) {
// Ignore and return plain password instead.
}
}
if (userInfo.plainText != null) {
boolean scramOnly = JiveGlobals.getBooleanProperty("user.scramHashedPasswordOnly");
if (scramOnly) {
// If we have a password here, but we're meant to be scramOnly, we should reset it.
setPassword(username, userInfo.plainText);
}
if (userInfo.salt == null) {
// RECURSE
return getUserInfo(username);
}
}
// Good to go.
return userInfo;
}
catch (SQLException sqle) {
Log.error("User SQL failure:", sqle);
throw new UserNotFoundException(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
@Override
public String getSalt(String username) throws UserNotFoundException {
return getUserInfo(username).salt;
}
@Override
public int getIterations(String username) throws UserNotFoundException {
return getUserInfo(username).iterations;
}
@Override
public String getStoredKey(String username) throws UserNotFoundException {
return getUserInfo(username).storedKey;
}
@Override
public String getServerKey(String username) throws UserNotFoundException {
return getUserInfo(username).serverKey;
}
@Override
public void authenticate(String username, String password) throws UnauthorizedException {
if (username == null || password == null) {
......
......@@ -232,4 +232,24 @@ public class HybridAuthProvider implements AuthProvider {
// TODO Auto-generated method stub
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
}
\ No newline at end of file
......@@ -448,7 +448,27 @@ public class JDBCAuthProvider implements AuthProvider, PropertyEventListener {
// TODO Auto-generated method stub
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
/**
* Support a subset of JDBCAuthProvider properties when updated via REST,
* web GUI, or other sources. Provider strings (and related settings) must
......
......@@ -139,4 +139,48 @@ public class MappedAuthProvider implements AuthProvider
return false;
}
@Override
public String getSalt(String username) throws UserNotFoundException
{
final AuthProvider provider = mapper.getAuthProvider( username );
if ( provider == null )
{
throw new UserNotFoundException();
}
return provider.getSalt( username );
}
@Override
public int getIterations(String username) throws UserNotFoundException
{
final AuthProvider provider = mapper.getAuthProvider( username );
if ( provider == null )
{
throw new UserNotFoundException();
}
return provider.getIterations( username );
}
@Override
public String getServerKey(String username) throws UserNotFoundException
{
final AuthProvider provider = mapper.getAuthProvider( username );
if ( provider == null )
{
throw new UserNotFoundException();
}
return provider.getServerKey( username );
}
@Override
public String getStoredKey(String username) throws UserNotFoundException
{
final AuthProvider provider = mapper.getAuthProvider( username );
if ( provider == null )
{
throw new UserNotFoundException();
}
return provider.getStoredKey( username );
}
}
......@@ -204,4 +204,24 @@ public class NativeAuthProvider implements AuthProvider {
// TODO Auto-generated method stub
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
}
......@@ -240,4 +240,24 @@ public class POP3AuthProvider implements AuthProvider {
public boolean isScramSupported() {
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
}
\ No newline at end of file
......@@ -107,4 +107,24 @@ public class CrowdAuthProvider implements AuthProvider {
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
}
......@@ -157,4 +157,24 @@ public class LdapAuthProvider implements AuthProvider {
public boolean isScramSupported() {
return false;
}
@Override
public String getSalt(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public int getIterations(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getServerKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
@Override
public String getStoredKey(String username) throws UnsupportedOperationException, UserNotFoundException {
throw new UnsupportedOperationException();
}
}
\ No newline at end of file
......@@ -38,7 +38,6 @@ import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.openfire.auth.ConnectionException;
import org.jivesoftware.openfire.auth.InternalUnauthenticatedException;
import org.jivesoftware.openfire.auth.ScramUtils;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -315,13 +314,13 @@ public class ScramSha1SaslServer implements SaslServer {
*/
private byte[] getSalt(final String username) {
try {
String saltshaker = UserManager.getUserProvider().loadUser(username).getSalt();
String saltshaker = AuthFactory.getSalt(username);
byte[] salt;
if (saltshaker == null) {
Log.debug("No salt found, so resetting password.");
String password = AuthFactory.getPassword(username);
AuthFactory.setPassword(username, password);
salt = DatatypeConverter.parseBase64Binary(UserManager.getUserProvider().loadUser(username).getSalt());
salt = DatatypeConverter.parseBase64Binary(AuthFactory.getSalt(username));
} else {
salt = DatatypeConverter.parseBase64Binary(saltshaker);
}
......@@ -338,14 +337,14 @@ public class ScramSha1SaslServer implements SaslServer {
* Retrieve the iteration count from the database for a given username.
*/
private int getIterations(final String username) throws UserNotFoundException {
return UserManager.getUserProvider().loadUser(username).getIterations();
return AuthFactory.getIterations(username);
}
/**
* Retrieve the server key from the database for a given username.
*/
private byte[] getServerKey(final String username) throws UserNotFoundException {
final String serverKey = UserManager.getUserProvider().loadUser( username ).getServerKey();
final String serverKey = AuthFactory.getServerKey(username);
if (serverKey == null) {
return null;
} else {
......@@ -357,7 +356,7 @@ public class ScramSha1SaslServer implements SaslServer {
* Retrieve the stored key from the database for a given username.
*/
private byte[] getStoredKey(final String username) throws UserNotFoundException {
final String storedKey = UserManager.getUserProvider().loadUser( username ).getStoredKey();
final String storedKey = AuthFactory.getStoredKey(username);
if (storedKey == null) {
return null;
} else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment