diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java index 74f435163..c9e1a5a28 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java @@ -448,11 +448,12 @@ class NetDbRenderer { buf.append("
"); for (LeaseSet ls : leases) { Destination dest = ls.getDestination(); - Hash key = dest.calculateHash(); + Hash key = ls.getHash(); buf.append("\n") .append(""); if (_context.clientManager().isLocal(dest)) { buf.append("\n\n\n\n"); + buf.append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp))); + buf.append("\n"); if (debug) { buf.append("
").append(_t("LeaseSet")).append(": ").append(key.toBase64()).append(""); - if (_context.keyRing().get(key) != null) - buf.append(" (").append(_t("Encrypted")).append(')'); + int type = ls.getType(); + if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2 || _context.keyRing().get(key) != null) + buf.append(" (").append(_t("Encrypted")).append(")"); buf.append("" + _t("Local") + " "); @@ -477,7 +478,7 @@ class NetDbRenderer { buf.append(" colspan=\"2\""); } buf.append(">"); - String b32 = dest.toBase32(); + String b32 = key.toBase32(); buf.append("").append(b32).append(""); if (linkSusi && !unpublished) { if (host == null) { @@ -505,13 +506,23 @@ class NetDbRenderer { } } } - buf.append("
\n"); - long exp = ls.getLatestLeaseDate()-now; + long exp; + if (type == DatabaseEntry.KEY_TYPE_LEASESET) { + exp = ls.getLatestLeaseDate() - now; + } else { + LeaseSet2 ls2 = (LeaseSet2) ls; + long pub = now - ls2.getPublished(); + buf.append("
\n") + .append(_t("Published {0} ago", DataHelper.formatDuration2(pub))) + .append(""); + exp = ((LeaseSet2)ls).getExpires()-now; + } + buf.append("
\n"); if (exp > 0) - buf.append("").append(_t("Expires in {0}", DataHelper.formatDuration2(exp))).append(""); + buf.append(_t("Expires in {0}", DataHelper.formatDuration2(exp))); else - buf.append("").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp))).append(""); - buf.append("
"); buf.append("RAP? ").append(ls.getReceivedAsPublished()); @@ -522,7 +533,6 @@ class NetDbRenderer { median = dist; } buf.append("  Distance: ").append(fmt.format(biLog2(dist))); - int type = ls.getType(); buf.append("  Type: ").append(type); if (type != DatabaseEntry.KEY_TYPE_LEASESET) { LeaseSet2 ls2 = (LeaseSet2) ls; diff --git a/core/java/src/net/i2p/data/EncryptedLeaseSet.java b/core/java/src/net/i2p/data/EncryptedLeaseSet.java index eb88cd86d..ba3a43df9 100644 --- a/core/java/src/net/i2p/data/EncryptedLeaseSet.java +++ b/core/java/src/net/i2p/data/EncryptedLeaseSet.java @@ -286,6 +286,8 @@ public class EncryptedLeaseSet extends LeaseSet2 { } /** + * This must be used instead of getDestination().getHash(). + * * Overridden because we have a blinded key, not a dest. * This is the hash of the signing public key type and the signing public key. * Throws IllegalStateException if not initialized. @@ -537,6 +539,9 @@ public class EncryptedLeaseSet extends LeaseSet2 { */ @Override public boolean verifySignature() { + // TODO use fields in super + if (_decryptedLS2 != null) + return _decryptedLS2.verifySignature(); if (_log.shouldDebug()) { _log.debug("Sig verify outer with key: " + _signingKey.getType() + ' ' + _signingKey.toBase64()); _log.debug("Outer sig: " + _signature.getType() + ' ' + _signature.toBase64()); @@ -596,6 +601,8 @@ public class EncryptedLeaseSet extends LeaseSet2 { StringBuilder buf = new StringBuilder(128); buf.append("[EncryptedLeaseSet: "); buf.append("\n\tBlinded Key: ").append(_signingKey); + buf.append("\n\tHash: ").append(getHash()); + buf.append("\n\tB32: ").append(getHash().toBase32()); if (isOffline()) { buf.append("\n\tTransient Key: ").append(_transientSigningPublicKey); buf.append("\n\tTransient Expires: ").append(new java.util.Date(_transientExpires)); diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java index 8af1af2f6..a594437ba 100644 --- a/core/java/src/net/i2p/data/LeaseSet.java +++ b/core/java/src/net/i2p/data/LeaseSet.java @@ -402,9 +402,9 @@ public class LeaseSet extends DatabaseEntry { StringBuilder buf = new StringBuilder(128); buf.append("[LeaseSet: "); buf.append("\n\tDestination: ").append(_destination); + buf.append("\n\tB32: ").append(_destination.toBase32()); buf.append("\n\tEncryptionKey: ").append(_encryptionKey); buf.append("\n\tSigningKey: ").append(_signingKey); - //buf.append("\n\tVersion: ").append(getVersion()); buf.append("\n\tSignature: ").append(_signature); buf.append("\n\tLeases: #").append(getLeaseCount()); for (int i = 0; i < getLeaseCount(); i++) diff --git a/core/java/src/net/i2p/data/LeaseSet2.java b/core/java/src/net/i2p/data/LeaseSet2.java index a91253b17..f545e037b 100644 --- a/core/java/src/net/i2p/data/LeaseSet2.java +++ b/core/java/src/net/i2p/data/LeaseSet2.java @@ -55,7 +55,7 @@ public class LeaseSet2 extends LeaseSet { /** * Published timestamp, as received. - * Different than getDate(), which is the earliest lease expiration. + * Different than getDate() or getEarliestLeaseDate(), which are the earliest lease expiration. * * @return in ms, with 1 second resolution * @since 0.9.39 @@ -64,6 +64,17 @@ public class LeaseSet2 extends LeaseSet { return _published; } + /** + * Published expiration, as received. + * May be different than getLatestLeaseDate(), which is the latest lease expiration. + * + * @return in ms, with 1 second resolution + * @since 0.9.39 + */ + public long getExpires() { + return _expires; + } + public boolean isUnpublished() { return (_flags & FLAG_UNPUBLISHED) != 0; } @@ -578,6 +589,7 @@ public class LeaseSet2 extends LeaseSet { StringBuilder buf = new StringBuilder(128); buf.append("[LeaseSet2: "); buf.append("\n\tDestination: ").append(_destination); + buf.append("\n\tB32: ").append(_destination.toBase32()); List keys = getEncryptionKeys(); int sz = keys.size(); buf.append("\n\tEncryption Keys: ").append(sz); diff --git a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java index 48c57bbd7..03793b627 100644 --- a/router/java/src/net/i2p/router/client/ClientMessageEventListener.java +++ b/router/java/src/net/i2p/router/client/ClientMessageEventListener.java @@ -17,6 +17,7 @@ import net.i2p.crypto.SigType; import net.i2p.data.DatabaseEntry; import net.i2p.data.DataHelper; import net.i2p.data.Destination; +import net.i2p.data.EncryptedLeaseSet; import net.i2p.data.Hash; import net.i2p.data.LeaseSet; import net.i2p.data.LeaseSet2; @@ -631,7 +632,16 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi } } try { + if (_log.shouldDebug()) + _log.debug("Publishing: " + ls); _context.netDb().publish(ls); + if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) { + // store the decrypted ls also + EncryptedLeaseSet encls = (EncryptedLeaseSet) ls; + if (_log.shouldDebug()) + _log.debug("Storing decrypted: " + encls.getDecryptedLeaseSet()); + _context.netDb().store(dest.getHash(), encls.getDecryptedLeaseSet()); + } } catch (IllegalArgumentException iae) { if (_log.shouldLog(Log.ERROR)) _log.error("Invalid leaseset from client", iae); @@ -642,7 +652,12 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi _log.info("New lease set granted for destination " + dest); // leaseSetCreated takes care of all the LeaseRequestState stuff (including firing any jobs) - _runner.leaseSetCreated(ls); + if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) { + EncryptedLeaseSet encls = (EncryptedLeaseSet) ls; + _runner.leaseSetCreated(encls.getDecryptedLeaseSet()); + } else { + _runner.leaseSetCreated(ls); + } } /** override for testing */ diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 37f8ef181..4950b943d 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -29,6 +29,7 @@ import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.KeyCertificate; import net.i2p.data.LeaseSet; +import net.i2p.data.LeaseSet2; import net.i2p.data.i2np.DatabaseLookupMessage; import net.i2p.data.i2np.DatabaseStoreMessage; import net.i2p.data.router.RouterAddress; @@ -683,7 +684,7 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad _log.warn("publish() before initialized: " + localLeaseSet, new Exception("I did it")); return; } - Hash h = localLeaseSet.getDestination().calculateHash(); + Hash h = localLeaseSet.getHash(); try { store(h, localLeaseSet); } catch (IllegalArgumentException iae) { @@ -798,10 +799,10 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad * @return reason why the entry is not valid, or null if it is valid */ private String validate(Hash key, LeaseSet leaseSet) throws UnsupportedCryptoException { - if (!key.equals(leaseSet.getDestination().calculateHash())) { + if (!key.equals(leaseSet.getHash())) { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid store attempt! key does not match leaseSet.destination! key = " - + key + ", leaseSet = " + leaseSet); + + key.toBase32() + ", leaseSet = " + leaseSet); return "Key does not match leaseSet.destination - " + key.toBase64(); } // todo experimental sig types @@ -812,8 +813,23 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad _log.warn("Invalid leaseSet signature! " + leaseSet); return "Invalid leaseSet signature on " + key; } - long earliest = leaseSet.getEarliestLeaseDate(); - long latest = leaseSet.getLatestLeaseDate(); + long earliest; + long latest; + int type = leaseSet.getType(); + if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) { + LeaseSet2 ls2 = (LeaseSet2) leaseSet; + // we'll assume it's not an encrypted meta, for now + earliest = ls2.getPublished(); + latest = ls2.getExpires(); + } else if (type == DatabaseEntry.KEY_TYPE_META_LS2) { + LeaseSet2 ls2 = (LeaseSet2) leaseSet; + // TODO this isn't right, and must adjust limits below also + earliest = Math.min(ls2.getEarliestLeaseDate(), ls2.getPublished()); + latest = Math.min(ls2.getLatestLeaseDate(), ls2.getExpires()); + } else { + earliest = leaseSet.getEarliestLeaseDate(); + latest = leaseSet.getLatestLeaseDate(); + } long now = _context.clock().now(); if (earliest <= now - 10*60*1000L || // same as the isCurrent(Router.CLOCK_FUDGE_FACTOR) test in