forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test2' (head c182b371bc28158dd47262b89e5bd0cdda29e07b)
to branch 'i2p.i2p' (head 4fc776f7b76b028bb890affccfdcfbefbb932c58)
This commit is contained in:
@@ -13,6 +13,7 @@ import net.i2p.data.Hash;
|
||||
import net.i2p.data.RouterInfo;
|
||||
import net.i2p.internal.InternalClientManager;
|
||||
import net.i2p.router.client.ClientManagerFacadeImpl;
|
||||
import net.i2p.router.crypto.TransientSessionKeyManager;
|
||||
import net.i2p.router.dummy.*;
|
||||
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||
import net.i2p.router.peermanager.PeerManagerFacadeImpl;
|
||||
@@ -67,7 +68,7 @@ public class RouterContext extends I2PAppContext {
|
||||
private final Set<Runnable> _finalShutdownTasks;
|
||||
// split up big lock on this to avoid deadlocks
|
||||
private volatile boolean _initialized;
|
||||
private final Object _lock1 = new Object(), _lock2 = new Object();
|
||||
private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object();
|
||||
|
||||
private static final List<RouterContext> _contexts = new CopyOnWriteArrayList<RouterContext>();
|
||||
|
||||
@@ -565,4 +566,20 @@ public class RouterContext extends I2PAppContext {
|
||||
public RouterAppManager routerAppManager() {
|
||||
return _appManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* As of 0.9.15, this returns a dummy SessionKeyManager in I2PAppContext.
|
||||
* Overridden in RouterContext to return the full TransientSessionKeyManager.
|
||||
*
|
||||
* @since 0.9.15
|
||||
*/
|
||||
@Override
|
||||
protected void initializeSessionKeyManager() {
|
||||
synchronized (_lock3) {
|
||||
if (_sessionKeyManager == null)
|
||||
//_sessionKeyManager = new PersistentSessionKeyManager(this);
|
||||
_sessionKeyManager = new TransientSessionKeyManager(this);
|
||||
_sessionKeyManagerInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.crypto.TransientSessionKeyManager;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
@@ -43,6 +42,7 @@ import net.i2p.data.i2cp.SessionId;
|
||||
import net.i2p.router.Job;
|
||||
import net.i2p.router.JobImpl;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.crypto.TransientSessionKeyManager;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
|
@@ -11,6 +11,7 @@ package net.i2p.router.client;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.CoreVersion;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.Payload;
|
||||
import net.i2p.data.i2cp.BandwidthLimitsMessage;
|
||||
@@ -195,10 +196,16 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Signature verified correctly on create session message");
|
||||
} else {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Signature verification *FAILED* on a create session message. Hijack attempt?");
|
||||
// For now, we do NOT send a SessionStatusMessage - see javadoc above
|
||||
_runner.disconnectClient("Invalid signature on CreateSessionMessage");
|
||||
int itype = in.getDestination().getCertificate().getCertificateType();
|
||||
SigType stype = SigType.getByCode(itype);
|
||||
if (stype == null || !stype.isAvailable()) {
|
||||
_log.error("Client requested unsupported signature type " + itype);
|
||||
_runner.disconnectClient("Unsupported signature type " + itype);
|
||||
} else {
|
||||
_log.error("Signature verification failed on a create session message");
|
||||
_runner.disconnectClient("Invalid signature on CreateSessionMessage");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
7
router/java/src/net/i2p/router/crypto/package.html
Normal file
7
router/java/src/net/i2p/router/crypto/package.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Classes formerly in net.i2p.crypto but moved here as they are only used by the router.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@@ -967,6 +967,32 @@ class EstablishmentManager {
|
||||
notifyActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from UDPReceiver.
|
||||
* Accelerate response to RelayResponse if we haven't sent it yet.
|
||||
*
|
||||
* @since 0.9.15
|
||||
*/
|
||||
void receiveHolePunch(InetAddress from, int fromPort) {
|
||||
RemoteHostId id = new RemoteHostId(from.getAddress(), fromPort);
|
||||
OutboundEstablishState state = _outboundStates.get(id);
|
||||
if (state != null) {
|
||||
boolean sendNow = state.receiveHolePunch();
|
||||
if (sendNow) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Hole punch from " + state + ", sending SessionRequest now");
|
||||
notifyActivity();
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Hole punch from " + state + ", already sent SessionRequest");
|
||||
}
|
||||
} else {
|
||||
// HolePunch received before RelayResponse, and we didn't know the IP/port, or it changed
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("No state found for hole punch from " + from + " port " + fromPort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Are IP and port valid? This is only for checking the relay response.
|
||||
* Reject all IPv6, for now, even if we are configured for it.
|
||||
|
@@ -99,6 +99,8 @@ class OutboundEstablishState {
|
||||
/** max delay including backoff */
|
||||
private static final long MAX_DELAY = 15*1000;
|
||||
|
||||
private static final long WAIT_FOR_HOLE_PUNCH_DELAY = 500;
|
||||
|
||||
/**
|
||||
* @param claimedAddress an IP/port based RemoteHostId, or null if unknown
|
||||
* @param remoteHostId non-null, == claimedAddress if direct, or a hash-based one if indirect
|
||||
@@ -556,7 +558,7 @@ class OutboundEstablishState {
|
||||
public synchronized void introduced(byte bobIP[], int bobPort) {
|
||||
if (_currentState != OutboundState.OB_STATE_PENDING_INTRO)
|
||||
return; // we've already successfully been introduced, so don't overwrite old settings
|
||||
_nextSend = _context.clock().now() + 500; // wait briefly for the hole punching
|
||||
_nextSend = _context.clock().now() + WAIT_FOR_HOLE_PUNCH_DELAY; // wait briefly for the hole punching
|
||||
_currentState = OutboundState.OB_STATE_INTRODUCED;
|
||||
if (_claimedAddress != null && bobPort == _bobPort && DataHelper.eq(bobIP, _bobIP)) {
|
||||
// he's who he said he was
|
||||
@@ -570,6 +572,24 @@ class OutboundEstablishState {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Introduced to " + _remoteHostId + ", now lets get on with establishing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Accelerate response to RelayResponse if we haven't sent it yet.
|
||||
*
|
||||
* @return true if we should send the SessionRequest now
|
||||
* @since 0.9.15
|
||||
*/
|
||||
synchronized boolean receiveHolePunch() {
|
||||
if (_currentState != OutboundState.OB_STATE_INTRODUCED)
|
||||
return false;
|
||||
if (_requestSentCount > 0)
|
||||
return false;
|
||||
long now = _context.clock().now();
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(toString() + " accelerating SessionRequest by " + (_nextSend - now) + " ms");
|
||||
_nextSend = now;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** how long have we been trying to establish this session? */
|
||||
public long getLifetime() { return _context.clock().now() - _establishBegin; }
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package net.i2p.router.transport.udp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -220,11 +221,12 @@ class UDPReceiver {
|
||||
// _socketChanged = false;
|
||||
//}
|
||||
UDPPacket packet = UDPPacket.acquire(_context, true);
|
||||
DatagramPacket dpacket = packet.getPacket();
|
||||
|
||||
// Android ICS bug
|
||||
// http://code.google.com/p/android/issues/detail?id=24748
|
||||
if (_isAndroid)
|
||||
packet.getPacket().setLength(UDPPacket.MAX_PACKET_SIZE);
|
||||
dpacket.setLength(UDPPacket.MAX_PACKET_SIZE);
|
||||
|
||||
// block before we read...
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
@@ -236,9 +238,9 @@ class UDPReceiver {
|
||||
//if (_log.shouldLog(Log.INFO))
|
||||
// _log.info("Before blocking socket.receive on " + System.identityHashCode(packet));
|
||||
//synchronized (Runner.this) {
|
||||
_socket.receive(packet.getPacket());
|
||||
_socket.receive(dpacket);
|
||||
//}
|
||||
int size = packet.getPacket().getLength();
|
||||
int size = dpacket.getLength();
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("After blocking socket.receive: packet is " + size + " bytes on " + System.identityHashCode(packet));
|
||||
packet.resetBegin();
|
||||
@@ -266,7 +268,8 @@ class UDPReceiver {
|
||||
_context.statManager().addRateData("udp.receiveHolePunch", 1);
|
||||
// nat hole punch packets are 0 bytes
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Received a 0 byte udp packet from " + packet.getPacket().getAddress() + ":" + packet.getPacket().getPort());
|
||||
_log.info("Received a 0 byte udp packet from " + dpacket.getAddress() + ":" + dpacket.getPort());
|
||||
_transport.getEstablisher().receiveHolePunch(dpacket.getAddress(), dpacket.getPort());
|
||||
packet.release();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
|
@@ -21,18 +21,21 @@
|
||||
|
||||
package org.cybergarage.xml.parser;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.cybergarage.xml.Node;
|
||||
import org.cybergarage.xml.Parser;
|
||||
import org.cybergarage.xml.ParserException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
|
||||
@@ -116,8 +119,25 @@ public class JaxpParser extends Parser
|
||||
org.cybergarage.xml.Node root = null;
|
||||
|
||||
try {
|
||||
// https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setExpandEntityReferences(false);
|
||||
try {
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
} catch (ParserConfigurationException pce) {}
|
||||
try {
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
} catch (ParserConfigurationException pce) {}
|
||||
try {
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
} catch (ParserConfigurationException pce) {}
|
||||
try {
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
} catch (ParserConfigurationException pce) {}
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
builder.setEntityResolver(new BlankingResolver());
|
||||
InputSource inSrc = new InputSource(new NullFilterInputStream(inStream));
|
||||
Document doc = builder.parse(inSrc);
|
||||
|
||||
@@ -163,4 +183,16 @@ public class JaxpParser extends Parser
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P -
|
||||
* http://stackoverflow.com/questions/5883542/disable-xml-validation-based-on-external-dtd-xsd
|
||||
*/
|
||||
private static class BlankingResolver implements EntityResolver {
|
||||
private static final byte[] DUMMY = new byte[0];
|
||||
|
||||
public InputSource resolveEntity(String arg0, String arg1) {
|
||||
return new InputSource(new ByteArrayInputStream(DUMMY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user