package at.fhj.swd14.pse.security;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.login.LoginException;
import javax.sql.DataSource;
import javax.transaction.SystemException;
import javax.transaction.Transaction;

import org.jboss.security.PicketBoxLogger;
import org.jboss.security.PicketBoxMessages;
import org.jboss.security.auth.spi.DatabaseServerLoginModule;

public class SecureDatabaseServerLoginModule extends DatabaseServerLoginModule {

    @Override
    protected boolean validatePassword(String inputPassword, String expectedPassword) {
        if (inputPassword == null || expectedPassword == null)
            return false;

        DatabasePrincipal principle = (DatabasePrincipal) getIdentity();
        String encodedPassword = PasswordHasher.getInstance().hash(inputPassword, principle.getSalt());
        return encodedPassword.equals(expectedPassword);
    }

    /**
     * Get the expected password for the current username available via the
     * getUsername() method. This is called from within the login() method after
     * the CallbackHandler has returned the username and candidate password.
     *
     * @return the valid password String
     */
    protected String getUsersPassword() throws LoginException {
        final String username = getUsername();

        Transaction tx = null;
        if (suspendResume) {
            // tx = TransactionDemarcationSupport.suspendAnyTransaction();
            try {
                if (tm == null)
                    throw PicketBoxMessages.MESSAGES.invalidNullTransactionManager();
                tx = tm.suspend();
            } catch (SystemException e) {
                throw new UnsupportedOperationException(e);
            }
        }

        InitialContext ctx;
        DataSource ds;
        try {
            ctx = new InitialContext();
            ds = (DataSource) ctx.lookup(dsJndiName);
        } catch (NamingException e) {
            LoginException le = new LoginException(
                    PicketBoxMessages.MESSAGES.failedToLookupDataSourceMessage(dsJndiName));
            le.initCause(e);
            throw le;
        }

        try {
            return retrievePasswordHash(ds, username);
        } finally {
            if (suspendResume) {
                // TransactionDemarcationSupport.resumeAnyTransaction(tx);
                try {
                    tm.resume(tx);
                } catch (Exception e) {
                    PicketBoxLogger.LOGGER.warn(e);
                }
            }
        }
    }

    private String retrievePasswordHash(final DataSource datasource, final String username) throws LoginException {
        try (Connection connection = datasource.getConnection()) {
            // Get the password
            PicketBoxLogger.LOGGER.traceExecuteQuery(principalsQuery, username);
            try (PreparedStatement ps = connection.prepareStatement(principalsQuery);) {
                ps.setString(1, username);
                try (ResultSet rs = ps.executeQuery()) {
                    if (!rs.next()) {
                        throw PicketBoxMessages.MESSAGES.noMatchingUsernameFoundInPrincipals();
                    }

                    final Long userId = rs.getLong(1);
                    final String password = rs.getString(2);
                    final String salt = rs.getString(3);

                    // Set the tenant and user properties on the custom principal
                    // there maybe a better place to do this, but this is the only place
                    // I can see it working without having to hit the database with
                    // another query.
                    DatabasePrincipal principle = (DatabasePrincipal) getIdentity();
                    principle.setUserId(userId);
                    principle.setSalt(salt);
                    return convertRawPassword(password);
                }
            }
        } catch (SQLException ex) {
            LoginException le = new LoginException(PicketBoxMessages.MESSAGES.failedToProcessQueryMessage());
            le.initCause(ex);
            throw le;
        }
    }

}

@@ -215,32 +215,87 @@
 amingException;%0A
+import javax.security.auth.login.FailedLoginException;%0A
 import javax.sec
@@ -3246,24 +3246,420 @@
             
+return processUserQueryResultSet(rs);%0A                %7D%0A            %7D%0A        %7D catch (SQLException ex) %7B%0A            LoginException le = new LoginException(PicketBoxMessages.MESSAGES.failedToProcessQueryMessage());%0A            le.initCause(ex);%0A            throw le;%0A        %7D%0A    %7D%0A%0A    private String processUserQueryResultSet(ResultSet rs) throws SQLException, FailedLoginException %7B%0A        
 if (!rs.next
@@ -3660,36 +3660,24 @@
 s.next()) %7B%0A
-            
             
@@ -3760,35 +3760,11 @@
     
-            %7D%0A%0A            
+%7D%0A%0A
     
@@ -3802,28 +3802,16 @@
 ong(1);%0A
-            
         
@@ -3851,28 +3851,16 @@
 ing(2);%0A
-            
         
@@ -3897,28 +3897,16 @@
 ng(3);%0A%0A
-            
         
@@ -3967,28 +3967,16 @@
 incipal%0A
-            
         
@@ -4044,28 +4044,16 @@
 y place%0A
-            
         
@@ -4116,28 +4116,16 @@
 se with%0A
-            
         
@@ -4142,28 +4142,16 @@
  query.%0A
-            
         
@@ -4211,36 +4211,24 @@
 Identity();%0A
-            
         prin
@@ -4248,36 +4248,24 @@
 Id(userId);%0A
-            
         prin
@@ -4285,28 +4285,16 @@
 (salt);%0A
-            
         
@@ -4334,248 +4334,8 @@
 d);%0A
-                %7D%0A            %7D%0A        %7D catch (SQLException ex) %7B%0A            LoginException le = new LoginException(PicketBoxMessages.MESSAGES.failedToProcessQueryMessage());%0A            le.initCause(ex);%0A            throw le;%0A        %7D%0A
     

fix sonar issue