From 5a4c2de425111f2d62e498f394bcf32b049c701f Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 23 Aug 2009 16:12:09 +0000 Subject: [PATCH] * Message, I2PSession, SessionKeyManager, Console: Prep for SessionKeyManager work in the router - Fix up SKM renderStatusHTML(); add debug.jsp to see it; Redefine getClientSessionKeyManager(); More cleanups --- apps/routerconsole/jsp/debug.jsp | 30 +++++++ .../client/MessagePayloadMessageHandler.java | 25 +++--- .../src/net/i2p/crypto/SessionKeyManager.java | 4 + .../crypto/TransientSessionKeyManager.java | 90 ++++++++++++------- .../net/i2p/router/ClientManagerFacade.java | 2 +- .../i2p/router/DummyClientManagerFacade.java | 2 +- .../net/i2p/router/client/ClientManager.java | 5 +- .../client/ClientManagerFacadeImpl.java | 2 +- 8 files changed, 115 insertions(+), 45 deletions(-) create mode 100644 apps/routerconsole/jsp/debug.jsp diff --git a/apps/routerconsole/jsp/debug.jsp b/apps/routerconsole/jsp/debug.jsp new file mode 100644 index 000000000..694f9c1df --- /dev/null +++ b/apps/routerconsole/jsp/debug.jsp @@ -0,0 +1,30 @@ +<%@page contentType="text/html"%> +<%@page pageEncoding="UTF-8"%> + +DEBUG +<%@include file="css.jsp" %> + +<%@include file="summary.jsp" %> +
+<% + /* + * Quick and easy place to put debugging stuff + */ + net.i2p.router.RouterContext ctx = (net.i2p.router.RouterContext) net.i2p.I2PAppContext.getGlobalContext(); + + /* + * Print out the status for all the SessionKeyManagers + */ + out.print("

Router SKM

"); + ctx.sessionKeyManager().renderStatusHTML(out); + java.util.Set clients = ctx.clientManager().listClients(); + for (net.i2p.data.Destination dest : clients) { + net.i2p.data.Hash h = dest.calculateHash(); + net.i2p.crypto.SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(h); + if (skm != null) { + out.print("

" + h.toBase64().substring(0,6) + " SKM

"); + skm.renderStatusHTML(out); + } + } +%> +
diff --git a/core/java/src/net/i2p/client/MessagePayloadMessageHandler.java b/core/java/src/net/i2p/client/MessagePayloadMessageHandler.java index 4b17a67d3..7b294e3b6 100644 --- a/core/java/src/net/i2p/client/MessagePayloadMessageHandler.java +++ b/core/java/src/net/i2p/client/MessagePayloadMessageHandler.java @@ -22,6 +22,8 @@ import net.i2p.util.Log; * of a message by accepting it, decrypting the payload, adding it to the set of * recieved messages, and telling the router that it has been recieved correctly. * + * We don't really decrypt (no more end-to-end crypto) + * * @author jrandom */ class MessagePayloadMessageHandler extends HandlerImpl { @@ -51,21 +53,24 @@ class MessagePayloadMessageHandler extends HandlerImpl { /** * Decrypt the payload + * + * We don't really decrypt (no more end-to-end crypto) + * If we do, we need to use the correct key manager in the decrypt() call below */ private Payload decryptPayload(MessagePayloadMessage msg, I2PSessionImpl session) throws DataFormatException { Payload payload = msg.getPayload(); - if (!I2CPMessageProducer.END_TO_END_CRYPTO) { + //if (!I2CPMessageProducer.END_TO_END_CRYPTO) { payload.setUnencryptedData(payload.getEncryptedData()); return payload; - } + //} - byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey()); - if (data == null) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Error decrypting the payload"); - throw new DataFormatException("Unable to decrypt the payload"); - } - payload.setUnencryptedData(data); - return payload; + //byte[] data = _context.elGamalAESEngine().decrypt(payload.getEncryptedData(), session.getDecryptionKey()); + //if (data == null) { + // if (_log.shouldLog(Log.WARN)) + // _log.warn("Error decrypting the payload"); + // throw new DataFormatException("Unable to decrypt the payload"); + //} + //payload.setUnencryptedData(data); + //return payload; } } diff --git a/core/java/src/net/i2p/crypto/SessionKeyManager.java b/core/java/src/net/i2p/crypto/SessionKeyManager.java index b1547864c..2cd86ba7d 100644 --- a/core/java/src/net/i2p/crypto/SessionKeyManager.java +++ b/core/java/src/net/i2p/crypto/SessionKeyManager.java @@ -9,6 +9,8 @@ package net.i2p.crypto; * */ +import java.io.IOException; +import java.io.Writer; import java.util.Set; import net.i2p.I2PAppContext; @@ -130,4 +132,6 @@ public class SessionKeyManager { */ public void shutdown() { // nop } + + public void renderStatusHTML(Writer out) throws IOException {} } diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java index 02be5acd5..2e034e2b1 100644 --- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java +++ b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java @@ -9,7 +9,10 @@ package net.i2p.crypto; * */ +import java.io.IOException; +import java.io.Writer; import java.util.ArrayList; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -17,6 +20,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; @@ -503,57 +507,83 @@ public class TransientSessionKeyManager extends SessionKeyManager { return removed; } - public String renderStatusHTML() { + @Override + public void renderStatusHTML(Writer out) throws IOException { StringBuilder buf = new StringBuilder(1024); - buf.append("

Inbound sessions

"); - buf.append(""); + buf.append("

Inbound sessions

" + + "
"); Set inbound = getInboundTagSets(); Map> inboundSets = new HashMap(inbound.size()); + // FIXME what does this loop do? nothing? for (Iterator iter = inbound.iterator(); iter.hasNext();) { TagSet ts = iter.next(); if (!inboundSets.containsKey(ts.getAssociatedKey())) inboundSets.put(ts.getAssociatedKey(), new HashSet()); Set sets = inboundSets.get(ts.getAssociatedKey()); sets.add(ts); } + int total = 0; + long now = _context.clock().now(); for (Iterator iter = inboundSets.keySet().iterator(); iter.hasNext();) { SessionKey skey = iter.next(); - Set sets = inboundSets.get(skey); - buf.append(""); - buf.append(""); - buf.append("" + + "" + + ""); + buf.append("\n"); + out.write(buf.toString()); + buf.setLength(0); } - buf.append("
Session key: ").append(skey.toBase64()).append("# Sets: ").append(sets.size()).append("
    "); + Set sets = new TreeSet(new TagSetComparator()); + sets.addAll(inboundSets.get(skey)); + buf.append("
Session key: ").append(skey.toBase64()).append("# Sets: ").append(sets.size()).append("
    "); for (Iterator siter = sets.iterator(); siter.hasNext();) { TagSet ts = siter.next(); - buf.append("
  • Received on: ").append(new Date(ts.getDate())).append(" with ") - .append(ts.getTags().size()).append(" tags remaining
  • "); + int size = ts.getTags().size(); + total += size; + buf.append("
  • Received: ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with "); + buf.append(size).append(" tags remaining
  • "); } - buf.append("
"); - - buf.append("

Outbound sessions

"); - - buf.append(""); + buf.append("\n" + + "
Total tags: ").append(total).append(" ("); + buf.append(DataHelper.formatSize(32*total)).append("B)
" + + "

Outbound sessions

" + + ""); + total = 0; Set outbound = getOutboundSessions(); for (Iterator iter = outbound.iterator(); iter.hasNext();) { OutboundSession sess = iter.next(); - buf.append(""); - buf.append(""); - buf.append("" + + "" + + ""); + buf.append("\n"); + out.write(buf.toString()); + buf.setLength(0); } - buf.append("
Target key: ").append(sess.getTarget().toString()).append("
"); - buf.append("Established: ").append(new Date(sess.getEstablishedDate())).append("
"); - buf.append("Last Used: ").append(new Date(sess.getLastUsedDate())).append("
"); - buf.append("# Sets: ").append(sess.getTagSets().size()).append("
Session key: ").append(sess.getCurrentKey().toBase64()).append("
    "); - for (Iterator siter = sess.getTagSets().iterator(); siter.hasNext();) { + Set sets = new TreeSet(new TagSetComparator()); + sets.addAll(sess.getTagSets()); + buf.append("
Target key: ").append(sess.getTarget().toString()).append("
" + + "Established: ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago
" + + "Last Used: ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago
" + + "# Sets: ").append(sess.getTagSets().size()).append("
Session key: ").append(sess.getCurrentKey().toBase64()).append("
    "); + for (Iterator siter = sets.iterator(); siter.hasNext();) { TagSet ts = siter.next(); - buf.append("
  • Sent on: ").append(new Date(ts.getDate())).append(" with ").append( - ts.getTags() - .size()) - .append(" tags remaining
  • "); + int size = ts.getTags().size(); + total += size; + buf.append("
  • Sent: ").append(DataHelper.formatDuration(now - ts.getDate())).append(" ago with "); + buf.append(size).append(" tags remaining
  • "); } - buf.append("
"); + buf.append("Total tags: ").append(total).append(" ("); + buf.append(DataHelper.formatSize(32*total)).append("B)\n" + + ""); - return buf.toString(); + out.write(buf.toString()); + } + + /** + * Just for the HTML method above so we can see what's going on easier + * Earliest first + */ + private class TagSetComparator implements Comparator { + public int compare(Object l, Object r) { + return (int) (((TagSet)l).getDate() - ((TagSet)r).getDate()); + } } class OutboundSession { @@ -760,7 +790,7 @@ public class TransientSessionKeyManager extends SessionKeyManager { @Override public int hashCode() { long rv = 0; - if (_key != null) rv = rv * 7 + _key.hashCode(); + if (_key != null) rv = _key.hashCode(); rv = rv * 7 + _date; // no need to hashCode the tags, key + date should be enough return (int) rv; diff --git a/router/java/src/net/i2p/router/ClientManagerFacade.java b/router/java/src/net/i2p/router/ClientManagerFacade.java index b6c377b70..131823287 100644 --- a/router/java/src/net/i2p/router/ClientManagerFacade.java +++ b/router/java/src/net/i2p/router/ClientManagerFacade.java @@ -92,6 +92,6 @@ public abstract class ClientManagerFacade implements Service { * */ public abstract SessionConfig getClientSessionConfig(Destination dest); - public abstract SessionKeyManager getClientSessionKeyManager(Destination dest); + public abstract SessionKeyManager getClientSessionKeyManager(Hash dest); public void renderStatusHTML(Writer out) throws IOException { } } diff --git a/router/java/src/net/i2p/router/DummyClientManagerFacade.java b/router/java/src/net/i2p/router/DummyClientManagerFacade.java index 5e362e3dd..9c0c6838e 100644 --- a/router/java/src/net/i2p/router/DummyClientManagerFacade.java +++ b/router/java/src/net/i2p/router/DummyClientManagerFacade.java @@ -41,7 +41,7 @@ public class DummyClientManagerFacade extends ClientManagerFacade { public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) {} public SessionConfig getClientSessionConfig(Destination _dest) { return null; } - public SessionKeyManager getClientSessionKeyManager(Destination _dest) { return null; } + public SessionKeyManager getClientSessionKeyManager(Hash _dest) { return null; } public void requestLeaseSet(Hash dest, LeaseSet set) {} diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index 8221a0bca..cbc5d778b 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -328,9 +328,10 @@ public class ClientManager { /** * Return the client's SessionKeyManager - * + * Use this instead of the RouterContext.sessionKeyManager() + * to prevent correlation attacks across destinations */ - public SessionKeyManager getClientSessionKeyManager(Destination dest) { + public SessionKeyManager getClientSessionKeyManager(Hash dest) { ClientConnectionRunner runner = getRunner(dest); if (runner != null) return runner.getSessionKeyManager(); diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java index 360cdb611..e90d12f53 100644 --- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java @@ -194,7 +194,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { * Return the client's current manager or null if not connected * */ - public SessionKeyManager getClientSessionKeyManager(Destination dest) { + public SessionKeyManager getClientSessionKeyManager(Hash dest) { if (_manager != null) return _manager.getClientSessionKeyManager(dest); else {