View | Details | Raw Unified | Return to bug 45871
Collapse All | Expand All

(-)DataSourceRealm.java (-4 / +161 lines)
Lines 24-29 Link Here
24
import java.sql.PreparedStatement;
24
import java.sql.PreparedStatement;
25
import java.sql.ResultSet;
25
import java.sql.ResultSet;
26
import java.sql.SQLException;
26
import java.sql.SQLException;
27
import java.text.MessageFormat;
27
import java.util.ArrayList;
28
import java.util.ArrayList;
28
29
29
import javax.naming.Context;
30
import javax.naming.Context;
Lines 68-73 Link Here
68
69
69
70
70
    /**
71
    /**
72
     * The generated string for the salt PreparedStatement
73
     */
74
    private String preparedSalt = null;
75
76
77
    /**
71
     * The name of the JNDI JDBC DataSource
78
     * The name of the JNDI JDBC DataSource
72
     */
79
     */
73
    protected String dataSourceName = null;
80
    protected String dataSourceName = null;
Lines 106-112 Link Here
106
113
107
114
108
    /**
115
    /**
109
     * The column in the user table that holds the user's credintials
116
     * The column in the user table that holds the user's credentials
110
     */
117
     */
111
    protected String userCredCol = null;
118
    protected String userCredCol = null;
112
119
Lines 118-123 Link Here
118
125
119
126
120
    /**
127
    /**
128
     * The column that holds the user's credentials salt
129
     */
130
    protected String userSaltCol = null;
131
    
132
    
133
    /**
134
     * A MessageFormat string that is used to salt the user's password before digesting.
135
     * Use {0} for the password and {1} for the salt. Default is {0}{1}.
136
     */
137
    protected String saltPattern = "{0}{1}";
138
    
139
    
140
    /**
121
     * The table that holds the relation between user's and roles
141
     * The table that holds the relation between user's and roles
122
     */
142
     */
123
    protected String userRoleTable = null;
143
    protected String userRoleTable = null;
Lines 201-206 Link Here
201
    }
221
    }
202
222
203
    /**
223
    /**
224
     * Return the column in the user table that holds the user's credential salt.
225
     */
226
    public String getUserSaltCol() {
227
        return userSaltCol;
228
    }
229
230
    /**
231
     * Set the column in the user table that holds the user's credential salt.
232
     * 
233
     * @param userSaltCol The column name
234
     */
235
    public void setUserSaltCol(String userSaltCol) {
236
        this.userSaltCol = userSaltCol;
237
    }
238
    
239
    /**
240
     * Get the <code>MessageFormat</code>-style pattern used to salt 
241
     * user passwords. The substitution strings are {0} for the user's
242
     * password and {1} for the salt.
243
     * 
244
     * @return the <code>MessageFormat</code>-style pattern used to 
245
     * salt user passwords.
246
     */
247
    public String getSaltPattern() {
248
        return saltPattern;
249
    }
250
251
    /**
252
     * Set the <code>MessageFormat</code>-style pattern used to salt
253
     * user passwords. The substitution strings are {0} for the user's 
254
     * password and {1} for the salt.
255
     * @param saltPattern the salt pattern.
256
     */
257
    public void setSaltPattern(String saltPattern) {
258
        this.saltPattern = saltPattern;
259
    }
260
261
    /**
204
     * Return the column in the user table that holds the user's name.
262
     * Return the column in the user table that holds the user's name.
205
     *
263
     *
206
     */
264
     */
Lines 323-336 Link Here
323
                                               String credentials) throws SQLException{
381
                                               String credentials) throws SQLException{
324
382
325
        String dbCredentials = getPassword(dbConnection, username);
383
        String dbCredentials = getPassword(dbConnection, username);
326
384
 
385
        String undigestedCredentials;
386
        if (isSalted() && hasMessageDigest()) {
387
            String dbSalt = getSalt(dbConnection, username);
388
            undigestedCredentials = MessageFormat.format(saltPattern,credentials,dbSalt);
389
        } else {
390
            undigestedCredentials = credentials;
391
        }
392
        
327
        // Validate the user's credentials
393
        // Validate the user's credentials
328
        boolean validated = false;
394
        boolean validated = false;
329
        if (hasMessageDigest()) {
395
        if (hasMessageDigest()) {
330
            // Hex hashes should be compared case-insensitive
396
            // Hex hashes should be compared case-insensitive
331
            validated = (digest(credentials).equalsIgnoreCase(dbCredentials));
397
            validated = (digest(undigestedCredentials).equalsIgnoreCase(dbCredentials));
332
        } else
398
        } else
333
            validated = (digest(credentials).equals(dbCredentials));
399
            validated = (digest(undigestedCredentials).equals(dbCredentials));
334
400
335
        if (validated) {
401
        if (validated) {
336
            if (containerLog.isTraceEnabled())
402
            if (containerLog.isTraceEnabled())
Lines 483-488 Link Here
483
549
484
550
485
    /**
551
    /**
552
     * Return the password salt associated with the given principal's user name.
553
     * @param dbConnection The database connection to be used
554
     * @param username Username for which password salt should be retrieved
555
     */
556
    protected String getSalt(Connection dbConnection, 
557
                                 String username) {
558
559
        ResultSet rs = null;
560
        PreparedStatement stmt = null;
561
        String dbSalt = null;
562
        try {
563
            stmt = salt(dbConnection, username);
564
            rs = stmt.executeQuery();
565
            if (rs.next()) {
566
                dbSalt = rs.getString(1);
567
            }
568
569
            return (dbSalt != null) ? dbSalt.trim() : null;
570
            
571
        } catch(SQLException e) {
572
            containerLog.error(
573
                    sm.getString("dataSourceRealm.getPassword.exception",
574
                                 username));
575
        } finally {
576
            try {
577
                if (rs != null) {
578
                    rs.close();
579
                }
580
                if (stmt != null) {
581
                    stmt.close();
582
                }
583
            } catch (SQLException e) {
584
                    containerLog.error(
585
                        sm.getString("dataSourceRealm.getPassword.exception",
586
                             username));
587
                
588
            }
589
        }
590
        
591
        return null;
592
    }
593
    
594
    
595
    /**
486
     * Return the Principal associated with the given user name.
596
     * Return the Principal associated with the given user name.
487
     */
597
     */
488
    protected Principal getPrincipal(String username) {
598
    protected Principal getPrincipal(String username) {
Lines 609-614 Link Here
609
719
610
    }
720
    }
611
721
722
723
    /**
724
     * Return a PreparedStatement configured to perform the SELECT required
725
     * to retrieve the password salt for the specified username.
726
     * 
727
     * @param dbConnection The database connection to be used
728
     * @param username Username for which the password salt should be retrieved
729
     * 
730
     * @return a PreparedStatement configured to perform the SELECT required
731
     * to retrieve the password salt for the specified username.
732
     * 
733
     * @throws SQLException if a database error occurs
734
     */
735
    private PreparedStatement salt(Connection dbConnection, String username)
736
        throws SQLException {
737
        
738
        PreparedStatement salt = 
739
            dbConnection.prepareStatement(preparedSalt);
740
        
741
        salt.setString(1, username);
742
        return salt;
743
    }
744
    
745
    
746
    /**
747
     * Return true if the password is being salted.
748
     * @return true if the password is salted in the database.
749
     */
750
    private boolean isSalted()
751
    {
752
        return userSaltCol != null && userSaltCol.length() > 0;
753
    }
754
    
755
    
612
    // ------------------------------------------------------ Lifecycle Methods
756
    // ------------------------------------------------------ Lifecycle Methods
613
757
614
758
Lines 643-648 Link Here
643
        temp.append(userNameCol);
787
        temp.append(userNameCol);
644
        temp.append(" = ?");
788
        temp.append(" = ?");
645
        preparedCredentials = temp.toString();
789
        preparedCredentials = temp.toString();
790
791
        // Create the salt PreparedStatement string
792
        if (isSalted())
793
        {
794
            temp = new StringBuffer("SELECT ");
795
            temp.append(userSaltCol);
796
            temp.append(" FROM ");
797
            temp.append(userTable);
798
            temp.append(" WHERE ");
799
            temp.append(userNameCol);
800
            temp.append(" = ?");
801
            preparedSalt = temp.toString();
802
        }
646
    }
803
    }
647
804
648
805

Return to bug 45871