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

(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/DataSourceRealm.java (-9 / +3 lines)
Lines 33-38 Link Here
33
import org.apache.catalina.LifecycleException;
33
import org.apache.catalina.LifecycleException;
34
import org.apache.catalina.ServerFactory;
34
import org.apache.catalina.ServerFactory;
35
import org.apache.catalina.core.StandardServer;
35
import org.apache.catalina.core.StandardServer;
36
import org.apache.catalina.util.HexUtils;
36
import org.apache.catalina.util.StringManager;
37
import org.apache.catalina.util.StringManager;
37
38
38
/**
39
/**
Lines 336-351 Link Here
336
                                               String credentials) throws SQLException{
337
                                               String credentials) throws SQLException{
337
338
338
        String dbCredentials = getPassword(dbConnection, username);
339
        String dbCredentials = getPassword(dbConnection, username);
339
340
 
340
        // Validate the user's credentials
341
        // Validate the user's credentials
341
        boolean validated = false;
342
        if (isValidEncodedPassword(credentials, dbCredentials)) {
342
        if (hasMessageDigest()) {
343
            // Hex hashes should be compared case-insensitive
344
            validated = (digest(credentials).equalsIgnoreCase(dbCredentials));
345
        } else
346
            validated = (digest(credentials).equals(dbCredentials));
347
348
        if (validated) {
349
            if (containerLog.isTraceEnabled())
343
            if (containerLog.isTraceEnabled())
350
                containerLog.trace(
344
                containerLog.trace(
351
                    sm.getString("dataSourceRealm.authenticateSuccess",
345
                    sm.getString("dataSourceRealm.authenticateSuccess",
(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JAASCallbackHandler.java (-1 / +1 lines)
Lines 69-75 Link Here
69
        this.username = username;
69
        this.username = username;
70
70
71
        if (realm.hasMessageDigest()) {
71
        if (realm.hasMessageDigest()) {
72
            this.password = realm.digest(password);
72
            this.password = realm.digest(password,null);
73
        }
73
        }
74
        else {
74
        else {
75
            this.password = password;
75
            this.password = password;
(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JDBCRealm.java (-10 / +3 lines)
Lines 29-34 Link Here
29
import java.util.Properties;
29
import java.util.Properties;
30
30
31
import org.apache.catalina.LifecycleException;
31
import org.apache.catalina.LifecycleException;
32
import org.apache.catalina.util.HexUtils;
32
import org.apache.catalina.util.StringManager;
33
import org.apache.catalina.util.StringManager;
33
34
34
35
Lines 413-428 Link Here
413
        // Look up the user's credentials
414
        // Look up the user's credentials
414
        String dbCredentials = getPassword(username);
415
        String dbCredentials = getPassword(username);
415
416
416
        // Validate the user's credentials
417
        // validate
417
        boolean validated = false;
418
        if (isValidEncodedPassword(credentials, dbCredentials)) {
418
        if (hasMessageDigest()) {
419
            // Hex hashes should be compared case-insensitive
420
            validated = (digest(credentials).equalsIgnoreCase(dbCredentials));
421
        } else {
422
            validated = (digest(credentials).equals(dbCredentials));
423
        }
424
425
        if (validated) {
426
            if (containerLog.isTraceEnabled())
419
            if (containerLog.isTraceEnabled())
427
                containerLog.trace(sm.getString("jdbcRealm.authenticateSuccess",
420
                containerLog.trace(sm.getString("jdbcRealm.authenticateSuccess",
428
                                                username));
421
                                                username));
(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/JNDIRealm.java (-3 / +4 lines)
Lines 1520-1529 Link Here
1520
                } // End synchronized(this) block
1520
                } // End synchronized(this) block
1521
            } else {
1521
            } else {
1522
                // Hex hashes should be compared case-insensitive
1522
                // Hex hashes should be compared case-insensitive
1523
                validated = (digest(credentials).equalsIgnoreCase(password));
1523
                validated = isValidEncodedPassword(credentials, password);
1524
            }
1524
            }
1525
        } else
1525
        } else {
1526
            validated = (digest(credentials).equals(password));
1526
            validated = isValidEncodedPassword(credentials, password);
1527
        }
1527
        return (validated);
1528
        return (validated);
1528
1529
1529
    }
1530
    }
(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/MemoryRealm.java (-13 / +2 lines)
Lines 25-30 Link Here
25
import java.util.HashMap;
25
import java.util.HashMap;
26
import java.util.Map;
26
import java.util.Map;
27
import org.apache.catalina.LifecycleException;
27
import org.apache.catalina.LifecycleException;
28
import org.apache.catalina.util.HexUtils;
28
import org.apache.catalina.util.StringManager;
29
import org.apache.catalina.util.StringManager;
29
import org.apache.juli.logging.Log;
30
import org.apache.juli.logging.Log;
30
import org.apache.juli.logging.LogFactory;
31
import org.apache.juli.logging.LogFactory;
Lines 147-165 Link Here
147
        GenericPrincipal principal =
148
        GenericPrincipal principal =
148
            (GenericPrincipal) principals.get(username);
149
            (GenericPrincipal) principals.get(username);
149
150
150
        boolean validated = false;
151
        if (principal != null && isValidEncodedPassword(credentials, principal.getPassword())) {
151
        if (principal != null && credentials != null) {
152
            if (hasMessageDigest()) {
153
                // Hex hashes should be compared case-insensitive
154
                validated = (digest(credentials)
155
                             .equalsIgnoreCase(principal.getPassword()));
156
            } else {
157
                validated =
158
                    (digest(credentials).equals(principal.getPassword()));
159
            }
160
        }
161
162
        if (validated) {
163
            if (log.isDebugEnabled())
152
            if (log.isDebugEnabled())
164
                log.debug(sm.getString("memoryRealm.authenticateSuccess", username));
153
                log.debug(sm.getString("memoryRealm.authenticateSuccess", username));
165
            return (principal);
154
            return (principal);
(-)orig/apache-tomcat-6.0.33-src/java/org/apache/catalina/realm/RealmBase.java (-33 / +92 lines)
Lines 28-33 Link Here
28
import java.security.Principal;
28
import java.security.Principal;
29
import java.security.cert.X509Certificate;
29
import java.security.cert.X509Certificate;
30
import java.util.ArrayList;
30
import java.util.ArrayList;
31
import java.util.Random;
31
32
32
import javax.management.Attribute;
33
import javax.management.Attribute;
33
import javax.management.MBeanRegistration;
34
import javax.management.MBeanRegistration;
Lines 104-109 Link Here
104
     */
105
     */
105
    protected static final String info =
106
    protected static final String info =
106
        "org.apache.catalina.realm.RealmBase/1.0";
107
        "org.apache.catalina.realm.RealmBase/1.0";
108
    
109
    /**
110
     * The number of salt bytes are at the end of the encoded password.
111
     */
112
    protected int saltBytes = 0;
107
113
108
114
109
    /**
115
    /**
Lines 227-233 Link Here
227
233
228
    }
234
    }
229
235
236
230
    /**
237
    /**
238
     * Returns the number of salt bytes that are included on the end of the encoded password
239
     * 
240
     * @return the number of salt bytes
241
     */
242
	public int getSaltBytes() {
243
		return saltBytes;
244
	}
245
246
247
	/**
248
	 * Sets the number of salt bytes that are on the end of the password
249
	 * 
250
	 * @param saltBytes the number of salt bytes to use
251
	 */
252
	public void setSaltBytes(int saltBytes) {
253
		this.saltBytes = saltBytes;
254
	}
255
256
	/**
231
     * Returns the digest encoding charset.
257
     * Returns the digest encoding charset.
232
     *
258
     *
233
     * @return The charset (may be null) for platform default
259
     * @return The charset (may be null) for platform default
Lines 245-250 Link Here
245
        digestEncoding = charset;
271
        digestEncoding = charset;
246
    }
272
    }
247
273
274
248
    /**
275
    /**
249
     * Return descriptive information about this Realm implementation and
276
     * Return descriptive information about this Realm implementation and
250
     * the corresponding version number, in the format
277
     * the corresponding version number, in the format
Lines 294-299 Link Here
294
321
295
    }
322
    }
296
323
324
    protected boolean isValidEncodedPassword(String credentials, String encodedPassword) {
325
        boolean validated ;
326
        if (encodedPassword == null ) {
327
            validated = false;
328
        } else if(hasMessageDigest()) {
329
        	byte[] salt = null;
330
        	if (saltBytes > 0 && encodedPassword.length() > 2*saltBytes) {
331
        		salt = HexUtils.convert(encodedPassword.substring(encodedPassword.length() - 2*saltBytes));
332
        	}
333
            validated = encodedPassword.equalsIgnoreCase(digest(credentials,salt));
334
        } else {
335
            validated = encodedPassword.equals(credentials);
336
        }
337
        return validated;
338
    }
297
339
298
    /**
340
    /**
299
     * Return the Principal associated with the specified username and
341
     * Return the Principal associated with the specified username and
Lines 304-321 Link Here
304
     *  authenticating this username
346
     *  authenticating this username
305
     */
347
     */
306
    public Principal authenticate(String username, String credentials) {
348
    public Principal authenticate(String username, String credentials) {
307
308
        String serverCredentials = getPassword(username);
349
        String serverCredentials = getPassword(username);
309
350
        if(!isValidEncodedPassword(credentials, serverCredentials)){
310
        boolean validated ;
311
        if ( serverCredentials == null ) {
312
            validated = false;
313
        } else if(hasMessageDigest()) {
314
            validated = serverCredentials.equalsIgnoreCase(digest(credentials));
315
        } else {
316
            validated = serverCredentials.equals(credentials);
317
        }
318
        if(! validated ) {
319
            if (containerLog.isTraceEnabled()) {
351
            if (containerLog.isTraceEnabled()) {
320
                containerLog.trace(sm.getString("realmBase.authenticateFailure",
352
                containerLog.trace(sm.getString("realmBase.authenticateFailure",
321
                                                username));
353
                                                username));
Lines 1107-1122 Link Here
1107
1139
1108
    // ------------------------------------------------------ Protected Methods
1140
    // ------------------------------------------------------ Protected Methods
1109
1141
1110
1111
    /**
1142
    /**
1112
     * Digest the password using the specified algorithm and
1143
     * Digest the password using the specified algorithm and
1113
     * convert the result to a corresponding hexadecimal string.
1144
     * convert the result to a corresponding hexadecimal string.
1114
     * If exception, the plain credentials string is returned.
1145
     * If exception, the plain credentials string is returned.
1146
     * If salt is not-null, the message digest is updated with
1147
     * that salt and it is appended to the string
1115
     *
1148
     *
1116
     * @param credentials Password or other credentials to use in
1149
     * @param credentials Password or other credentials to use in
1117
     *  authenticating this username
1150
     *  authenticating this username
1118
     */
1151
     */
1119
    protected String digest(String credentials)  {
1152
    protected String digest(String credentials,byte[] salt)  {
1120
1153
1121
        // If no MessageDigest instance is specified, return unchanged
1154
        // If no MessageDigest instance is specified, return unchanged
1122
        if (hasMessageDigest() == false)
1155
        if (hasMessageDigest() == false)
Lines 1139-1144 Link Here
1139
                    }
1172
                    }
1140
                }
1173
                }
1141
                md.update(bytes);
1174
                md.update(bytes);
1175
                if (salt != null) {
1176
                	md.update(salt);
1177
                    return (HexUtils.convert(md.digest())) + HexUtils.convert(salt);
1178
                }
1142
1179
1143
                return (HexUtils.convert(md.digest()));
1180
                return (HexUtils.convert(md.digest()));
1144
            } catch (Exception e) {
1181
            } catch (Exception e) {
Lines 1237-1243 Link Here
1237
     * @param encoding Character encoding of the string to digest
1274
     * @param encoding Character encoding of the string to digest
1238
     */
1275
     */
1239
    public final static String Digest(String credentials, String algorithm,
1276
    public final static String Digest(String credentials, String algorithm,
1240
                                      String encoding) {
1277
                                      String encoding, int saltBytes) {
1241
1278
1242
        try {
1279
        try {
1243
            // Obtain a new message digest with "digest" encryption
1280
            // Obtain a new message digest with "digest" encryption
Lines 1251-1259 Link Here
1251
            } else {
1288
            } else {
1252
                md.update(credentials.getBytes(encoding));                
1289
                md.update(credentials.getBytes(encoding));                
1253
            }
1290
            }
1254
1291
            if (saltBytes > 0) {
1255
            // Digest the credentials and return as hexadecimal
1292
            	Random r = new Random();
1256
            return (HexUtils.convert(md.digest()));
1293
            	byte[] salt = new byte[saltBytes];
1294
            	for(int i = 0; i < salt.length; i++) {
1295
            		salt[i] = (byte)r.nextInt(256);
1296
            	}
1297
            	md.update(salt);
1298
            	return (HexUtils.convert(md.digest())) + HexUtils.convert(salt);
1299
            } else {
1300
            	// Digest the credentials and return as hexadecimal
1301
            	return (HexUtils.convert(md.digest()));
1302
            }
1257
        } catch(Exception ex) {
1303
        } catch(Exception ex) {
1258
            log.error(ex);
1304
            log.error(ex);
1259
            return credentials;
1305
            return credentials;
Lines 1270-1292 Link Here
1270
    public static void main(String args[]) {
1316
    public static void main(String args[]) {
1271
1317
1272
        String encoding = null;
1318
        String encoding = null;
1273
        int firstCredentialArg = 2;
1319
        String algorithm = null;
1274
        
1320
        int saltBytes = 0;
1275
        if (args.length > 4 && args[2].equalsIgnoreCase("-e")) {
1321
        int arg = 0;
1276
            encoding = args[3];
1322
      
1277
            firstCredentialArg = 4;
1323
        while (arg + 1 < args.length && args[arg].startsWith("-")) {
1324
        	if (args[arg].equals("-a") && arg + 2 < args.length) {
1325
        		algorithm = args[arg+1];
1326
        		arg += 2;
1327
        	} else if (args[arg].equals("-e")) {
1328
        		encoding = args[arg+1];
1329
        		arg += 2;
1330
        	} else if (args[arg].equals("-s")) {
1331
        		saltBytes = Integer.parseInt(args[arg+1]);
1332
        		arg += 2;
1333
        	} else if (args[arg].equals("-")) { // on the off chance that someone needs to hash a password starting with a -
1334
        		arg++;
1335
        		break;
1336
        	} else {
1337
        		break;
1338
        	}
1339
        }
1340
1341
        if (algorithm == null) {
1342
            System.out.println("Usage: RealmBase -a <algorithm> [-s <salt bytes>] [-e <encoding>] <credentials>");
1343
        	System.exit(1);
1344
        }
1345
        for (; arg < args.length; arg++) {
1346
        	System.out.print(args[arg]+":");
1347
        	System.out.println(Digest(args[arg],algorithm,encoding,saltBytes));
1278
        }
1348
        }
1279
        
1280
        if(args.length > firstCredentialArg && args[0].equalsIgnoreCase("-a")) {
1281
            for(int i=firstCredentialArg; i < args.length ; i++){
1282
                System.out.print(args[i]+":");
1283
                System.out.println(Digest(args[i], args[1], encoding));
1284
            }
1285
        } else {
1286
            System.out.println
1287
                ("Usage: RealmBase -a <algorithm> [-e <encoding>] <credentials>");
1288
        }
1289
1290
    }
1349
    }
1291
1350
1292
1351

Return to bug 51966