diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java index da0f41c74957ad2f5d95b739981a886de3874820..d4581140916eb4044fb7fc787068cafdc93401b9 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUIHandler.java @@ -70,8 +70,7 @@ public class ConfigUIHandler extends FormHandler { } ConsolePasswordManager mgr = new ConsolePasswordManager(_context); // rfc 2617 - pw = name + ':' + RouterConsoleRunner.JETTY_REALM + ':' + pw; - if (mgr.saveMD5(RouterConsoleRunner.PROP_CONSOLE_PW, name, pw)) { + if (mgr.saveMD5(RouterConsoleRunner.PROP_CONSOLE_PW, RouterConsoleRunner.JETTY_REALM, name, pw)) { addFormNotice(_("Added user {0}", name)); addFormNotice(_("Restart required to take effect")); } else { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConsolePasswordManager.java b/apps/routerconsole/java/src/net/i2p/router/web/ConsolePasswordManager.java index 6c97a0eb1f0a6edeae42d26d95fcb424abf931ea..4a9babbb0f6fa7c7e0c9dccddd56de88c49e0fe2 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConsolePasswordManager.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConsolePasswordManager.java @@ -1,8 +1,5 @@ package net.i2p.router.web; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -35,20 +32,6 @@ public class ConsolePasswordManager extends RouterPasswordManager { migrateConsole(); } - /** - * Checks both plaintext and hash - * - * @param realm e.g. i2cp, routerconsole, etc. - * @param user null or "" for no user, already trimmed - * @param pw plain text, already trimmed - * @return if pw verified - */ - public boolean check(String realm, String user, String pw) { - return super.check(realm, user, pw) || - //checkCrypt(realm, user, pw) || - checkMD5(realm, user, pw); - } - /** * The username is the salt * @@ -77,23 +60,14 @@ public class ConsolePasswordManager extends RouterPasswordManager { * @param pw plain text, already trimmed * @return if pw verified */ - public boolean checkMD5(String realm, String user, String pw) { + public boolean checkMD5(String realm, String subrealm, String user, String pw) { String pfx = realm; if (user != null && user.length() > 0) pfx += '.' + user; String hex = _context.getProperty(pfx + PROP_MD5); if (hex == null) return false; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(pw.getBytes("ISO-8859-1")); - // must use the method that adds leading zeros - return hex.equals(DataHelper.toString(md.digest())); - } catch (UnsupportedEncodingException uee) { - return false; - } catch (NoSuchAlgorithmException nsae) { - return false; - } + return hex.equals(md5Hex(subrealm, user, pw)); } /** @@ -132,8 +106,8 @@ public class ConsolePasswordManager extends RouterPasswordManager { String pw = _context.getProperty(PROP_CONSOLE_OLD); if (pw != null) { if (pw.length() > 0) { - pw = CONSOLE_USER + ':' + RouterConsoleRunner.JETTY_REALM + ':' + pw; - saveMD5(RouterConsoleRunner.PROP_CONSOLE_PW, CONSOLE_USER, pw); + saveMD5(RouterConsoleRunner.PROP_CONSOLE_PW, RouterConsoleRunner.JETTY_REALM, + CONSOLE_USER, pw); } Map toAdd = Collections.singletonMap(PROP_MIGRATED, "true"); List toDel = Collections.singletonList(PROP_CONSOLE_OLD); @@ -172,32 +146,28 @@ public class ConsolePasswordManager extends RouterPasswordManager { /** * Straight MD5, no salt + * Compatible with Jetty and RFC 2617. * * @param realm The full realm, e.g. routerconsole.auth.i2prouter, etc. - * @param user null or "" for no user, already trimmed - * @param pw plain text, must be of the form user:realm:pw to be compatible with Jetty + * @param subrealm to be used in creating the checksum + * @param user non-null, non-empty, already trimmed + * @param pw plain text * @return if pw verified */ - public boolean saveMD5(String realm, String user, String pw) { + public boolean saveMD5(String realm, String subrealm, String user, String pw) { String pfx = realm; if (user != null && user.length() > 0) pfx += '.' + user; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(pw.getBytes("ISO-8859-1")); - String hex = DataHelper.toString(md.digest()); - Map<String, String> toAdd = Collections.singletonMap(pfx + PROP_MD5, hex); - List<String> toDel = new ArrayList(4); - toDel.add(pfx + PROP_PW); - toDel.add(pfx + PROP_B64); - toDel.add(pfx + PROP_CRYPT); - toDel.add(pfx + PROP_SHASH); - return _context.router().saveConfig(toAdd, toDel); - } catch (UnsupportedEncodingException uee) { - return false; - } catch (NoSuchAlgorithmException nsae) { + String hex = md5Hex(subrealm, user, pw); + if (hex == null) return false; - } + Map<String, String> toAdd = Collections.singletonMap(pfx + PROP_MD5, hex); + List<String> toDel = new ArrayList(4); + toDel.add(pfx + PROP_PW); + toDel.add(pfx + PROP_B64); + toDel.add(pfx + PROP_CRYPT); + toDel.add(pfx + PROP_SHASH); + return _context.router().saveConfig(toAdd, toDel); } public static void main(String args[]) { @@ -221,9 +191,9 @@ public class ConsolePasswordManager extends RouterPasswordManager { System.out.println("Fail 5"); System.out.println("Test MD5"); - if (!pm.saveMD5("type3", "user3", "pw3")) + if (!pm.saveMD5("type3", "realm", "user3", "pw3")) System.out.println("Fail 6"); - if (!pm.checkMD5("type3", "user3", "pw3")) + if (!pm.checkMD5("type3", "realm", "user3", "pw3")) System.out.println("Fail 7"); //System.out.println("Test crypt"); diff --git a/core/java/src/net/i2p/util/PasswordManager.java b/core/java/src/net/i2p/util/PasswordManager.java index fa2e339480514afe817ab7b3adbb58802408d1e5..9e0a2ffaeb3ecac9fdbbfe03169fd73abbea191d 100644 --- a/core/java/src/net/i2p/util/PasswordManager.java +++ b/core/java/src/net/i2p/util/PasswordManager.java @@ -1,5 +1,9 @@ package net.i2p.util; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + import net.i2p.I2PAppContext; import net.i2p.data.Base64; import net.i2p.data.DataHelper; @@ -144,4 +148,27 @@ public class PasswordManager { return null; return Base64.decodeToString(b64); } + + /** + * Straight MD5, no salt + * Will return the MD5 sum of "user:subrealm:pw", compatible with Jetty + * and RFC 2617. + * + * @param subrealm to be used in creating the checksum + * @param user non-null, non-empty, already trimmed + * @param pw non-null, plain text, already trimmed + * @return lower-case hex with leading zeros, 32 chars, or null on error + */ + public static String md5Hex(String subrealm, String user, String pw) { + String fullpw = user + ':' + subrealm + ':' + pw; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(fullpw.getBytes("ISO-8859-1")); + // adds leading zeros if necessary + return DataHelper.toString(md.digest()); + } catch (UnsupportedEncodingException uee) { + } catch (NoSuchAlgorithmException nsae) { + } + return null; + } }