propagate from branch 'i2p.i2p.zzz.test2' (head c182b371bc28158dd47262b89e5bd0cdda29e07b)

to branch 'i2p.i2p' (head 4fc776f7b76b028bb890affccfdcfbefbb932c58)
This commit is contained in:
zzz
2014-08-10 13:56:15 +00:00
30 changed files with 594 additions and 157 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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

View 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>

View File

@@ -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.

View File

@@ -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; }

View File

@@ -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) {

View File

@@ -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));
}
}
}