From 977cdee0465ae683c6e0a877161b4bedda4f92b7 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Mon, 15 Oct 2012 12:28:45 +0000
Subject: [PATCH]   - Move MD5 functions to core util where i2ptunnel can use
 them

---
 .../net/i2p/router/web/ConfigUIHandler.java   |  3 +-
 .../router/web/ConsolePasswordManager.java    | 70 ++++++-------------
 .../src/net/i2p/util/PasswordManager.java     | 27 +++++++
 3 files changed, 48 insertions(+), 52 deletions(-)

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 da0f41c749..d458114091 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 6c97a0eb1f..4a9babbb0f 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 fa2e339480..9e0a2ffaeb 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;
+    }
 }
-- 
GitLab