001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2005.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: *
019: * Created: 06-Jan-2005 by jejking
020: * Version: $Revision: 1.1 $
021: * Last Updated: $Date: 2005/01/07 16:54:36 $
022: */
023: package org.openharmonise.rm.security.authentication;
024:
025: import java.sql.*;
026:
027: /**
028: * Utility to move users from an environment using plain text password
029: * storage to one using hashed passwords.
030: *
031: * @author jejking
032: * @version $Revision: 1.1 $
033: */
034: public class PasswordMigrationUtil {
035:
036: private String hashAlgorithm;
037: private String dbUrl;
038: private String dbUsr;
039: private String dbPassword;
040:
041: public PasswordMigrationUtil(String hashAlgorithm, String dbDriver,
042: String dbUsr, String dbPassword, String dbUrl) {
043:
044: if (hashAlgorithm.equals("MD5")
045: || hashAlgorithm.equals("SHA-1")) {
046: this .hashAlgorithm = hashAlgorithm;
047: } else {
048: System.err.println("Non supported hash algorithm"
049: + hashAlgorithm);
050: System.exit(1);
051: }
052:
053: this .dbUrl = dbUrl;
054: this .dbUsr = dbUsr;
055: this .dbPassword = dbPassword;
056:
057: try {
058: Class.forName(dbDriver);
059: } catch (Exception e) {
060: e.printStackTrace();
061: System.exit(2);
062: }
063: }
064:
065: public void execute() {
066: // for all other users
067: // create salt
068: // combine salt with existing password to create the hash required
069:
070: try {
071: Connection con = DriverManager.getConnection(dbUrl, dbUsr,
072: dbPassword);
073: Statement getUsers = con.createStatement();
074: ResultSet usersRS = getUsers
075: .executeQuery("select id, password from users");
076: while (usersRS.next()) {
077: int id = usersRS.getInt("id");
078: System.out.println("Processing user with id " + id);
079:
080: String curPasswd = usersRS.getString("password");
081: // create a salt
082: String salt = getSalt(hashAlgorithm);
083: // create the hashed password
084: String hashedPasswd = getPasswordHelper(hashAlgorithm)
085: .getNewPassword(curPasswd, salt);
086:
087: // update the users table with the salt and the hashed password
088: Statement updateUser = con.createStatement();
089: updateUser.executeUpdate("update users set salt = '"
090: + salt + "', password = '" + hashedPasswd
091: + "' where id = " + id);
092: updateUser.close();
093: // update the users_hist table with the salt for all previous versions of the user
094: Statement updatePreviousSalts = con.createStatement();
095: updatePreviousSalts
096: .executeUpdate("update users_hist set salt = '"
097: + salt + "' where id = " + id);
098:
099: updatePreviousSalts.close();
100:
101: }
102: usersRS.close();
103: getUsers.close();
104: con.close();
105: } catch (SQLException e) {
106: // TODO Auto-generated catch block
107: e.printStackTrace();
108: }
109:
110: // and do the same for their previous versions
111: try {
112: Connection con = DriverManager.getConnection(dbUrl, dbUsr,
113: dbPassword);
114: Statement getPreviousUserVersions = con.createStatement();
115: // salt will already have been updated from the previous SQL
116: ResultSet previousUserVersionsRS = getPreviousUserVersions
117: .executeQuery("select object_key, salt, password from users_hist");
118: while (previousUserVersionsRS.next()) {
119: int object_key = previousUserVersionsRS
120: .getInt("object_key");
121: String salt = previousUserVersionsRS.getString("salt");
122: if (salt == null) {
123: continue; // not an active user
124: }
125: String previousPasswd = previousUserVersionsRS
126: .getString("password");
127: // create the hashed password
128: String hashedPasswd = getPasswordHelper(hashAlgorithm)
129: .getNewPassword(previousPasswd, salt);
130: // update it
131: Statement updatePreviousVersion = con.createStatement();
132: updatePreviousVersion
133: .executeUpdate("update users_hist set password = '"
134: + hashedPasswd
135: + "' where object_key = " + object_key);
136: updatePreviousVersion.close();
137: }
138: previousUserVersionsRS.close();
139:
140: Statement setPwdEncryption = con.createStatement();
141: setPwdEncryption
142: .executeUpdate("update oh_prop set prop_value = '"
143: + hashAlgorithm
144: + "' where prop_name = 'PWD_ENCRYPTION'");
145: setPwdEncryption.close();
146:
147: con.close();
148: } catch (SQLException sqlE) {
149: sqlE.printStackTrace();
150: }
151:
152: try {
153: Connection con = DriverManager.getConnection(dbUrl, dbUsr,
154: dbPassword);
155: //we now need to deal with any users who have been completely archived as
156: // their salt is null
157:
158: Statement getDefunctUsers = con.createStatement();
159: ResultSet defunctUsersRS = getDefunctUsers
160: .executeQuery("select distinct id from users_hist where salt is null");
161: while (defunctUsersRS.next()) {
162: // give them a salt
163: int id = defunctUsersRS.getInt("id");
164: String salt = getSalt(hashAlgorithm);
165: System.err.println("updating id " + id + " with salt "
166: + salt);
167: Statement updateSaltForDefunctUsers = con
168: .createStatement();
169: updateSaltForDefunctUsers
170: .executeUpdate("update users_hist set salt = '"
171: + salt + "' where id = " + id);
172: // no need to crypt defunct users' old passwords, really
173: updateSaltForDefunctUsers.close();
174: }
175: defunctUsersRS.close();
176: getDefunctUsers.close();
177: con.close();
178: } catch (SQLException e) {
179: e.printStackTrace();
180: }
181:
182: }
183:
184: private String getSalt(String algorithm) {
185: if (algorithm.equals("MD5")) {
186: return PasswordCryptUtil.getNewSalt(32);
187: } else {
188: return PasswordCryptUtil.getNewSalt(40);
189: }
190: }
191:
192: private PasswordHelper getPasswordHelper(String algorithm) {
193: return new CryptPasswordHelper(algorithm);
194: }
195:
196: public static void main(String[] args) {
197: PasswordMigrationUtil app = new PasswordMigrationUtil(args[0],
198: args[1], args[2], args[3], args[4]);
199: app.execute();
200: }
201: }
|