Search in sources :

Example 11 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class InboundMessageDistributor method distribute.

public void distribute(I2NPMessage msg, Hash target, TunnelId tunnel) {
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("IBMD for " + _client + " to " + target + " / " + tunnel + " : " + msg);
    // allow messages on client tunnels even after client disconnection, as it may
    // include e.g. test messages, etc.  DataMessages will be dropped anyway
    /*
        if ( (_client != null) && (!_context.clientManager().isLocal(_client)) ) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Not distributing a message, as it came down a client's tunnel (" 
                          + _client.toBase64() + ") after the client disconnected: " + msg);
            return;
        }
        */
    int type = msg.getType();
    // if the message came down a client tunnel:
    if (_client != null) {
        switch(type) {
            case DatabaseSearchReplyMessage.MESSAGE_TYPE:
                /**
                 **
                 *                     DatabaseSearchReplyMessage orig = (DatabaseSearchReplyMessage) msg;
                 *                     if (orig.getNumReplies() > 0) {
                 *                         if (_log.shouldLog(Log.INFO))
                 *                             _log.info("Removing replies from a DSRM down a tunnel for " + _client + ": " + msg);
                 *                         DatabaseSearchReplyMessage newMsg = new DatabaseSearchReplyMessage(_context);
                 *                         newMsg.setFromHash(orig.getFromHash());
                 *                         newMsg.setSearchKey(orig.getSearchKey());
                 *                         msg = newMsg;
                 *                     }
                 ***
                 */
                break;
            case DatabaseStoreMessage.MESSAGE_TYPE:
                DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
                if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
                    // Todo: if peer was ff and RI is not ff, queue for exploration in netdb (but that isn't part of the facade now)
                    if (_log.shouldLog(Log.WARN))
                        _log.warn("Dropping DSM down a tunnel for " + _client + ": " + msg);
                    // Handle safely by just updating the caps table, after doing basic validation
                    Hash key = dsm.getKey();
                    if (_context.routerHash().equals(key))
                        return;
                    RouterInfo ri = (RouterInfo) dsm.getEntry();
                    if (!key.equals(ri.getIdentity().getHash()))
                        return;
                    if (!ri.isValid())
                        return;
                    RouterInfo oldri = _context.netDb().lookupRouterInfoLocally(key);
                    // only update if RI is newer and non-ff
                    if (oldri != null && oldri.getPublished() < ri.getPublished() && !FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
                        if (_log.shouldLog(Log.WARN))
                            _log.warn("Updating caps for RI " + key + " from \"" + oldri.getCapabilities() + "\" to \"" + ri.getCapabilities() + '"');
                        _context.peerManager().setCapabilities(key, ri.getCapabilities());
                    }
                    return;
                } else if (dsm.getReplyToken() != 0) {
                    _context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, type);
                    _log.error("Dropping LS DSM w/ reply token down a tunnel for " + _client + ": " + msg);
                    return;
                } else {
                    // allow DSM of our own key (used by FloodfillVerifyStoreJob)
                    // or other keys (used by IterativeSearchJob)
                    // as long as there's no reply token (we will never set a reply token but an attacker might)
                    ((LeaseSet) dsm.getEntry()).setReceivedAsReply();
                }
                break;
            case DeliveryStatusMessage.MESSAGE_TYPE:
            case GarlicMessage.MESSAGE_TYPE:
            case TunnelBuildReplyMessage.MESSAGE_TYPE:
            case VariableTunnelBuildReplyMessage.MESSAGE_TYPE:
                // these are safe, handled below
                break;
            default:
                // drop it, since we should only get the above message types down
                // client tunnels
                _context.statManager().addRateData("tunnel.dropDangerousClientTunnelMessage", 1, type);
                _log.error("Dropped dangerous message down a tunnel for " + _client + ": " + msg, new Exception("cause"));
                return;
        }
    // switch
    } else {
        // expl. tunnel
        switch(type) {
            case DatabaseStoreMessage.MESSAGE_TYPE:
                DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
                if (dsm.getReplyToken() != 0) {
                    _context.statManager().addRateData("tunnel.dropDangerousExplTunnelMessage", 1, type);
                    _log.error("Dropping DSM w/ reply token down a expl. tunnel: " + msg);
                    return;
                }
                if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_LEASESET)
                    ((LeaseSet) dsm.getEntry()).setReceivedAsReply();
                break;
            case DatabaseSearchReplyMessage.MESSAGE_TYPE:
            case DeliveryStatusMessage.MESSAGE_TYPE:
            case GarlicMessage.MESSAGE_TYPE:
            case TunnelBuildReplyMessage.MESSAGE_TYPE:
            case VariableTunnelBuildReplyMessage.MESSAGE_TYPE:
                // these are safe, handled below
                break;
            default:
                _context.statManager().addRateData("tunnel.dropDangerousExplTunnelMessage", 1, type);
                _log.error("Dropped dangerous message down expl tunnel: " + msg, new Exception("cause"));
                return;
        }
    // switch
    }
    if ((target == null) || ((tunnel == null) && (_context.routerHash().equals(target)))) {
        // make sure we don't honor any remote requests directly (garlic instructions, etc)
        if (type == GarlicMessage.MESSAGE_TYPE) {
            // in case we're looking for replies to a garlic message (cough load tests cough)
            _context.inNetMessagePool().handleReplies(msg);
            // if (_log.shouldLog(Log.DEBUG))
            // _log.debug("received garlic message in the tunnel, parse it out");
            _receiver.receive((GarlicMessage) msg);
        } else {
            if (_log.shouldLog(Log.INFO))
                _log.info("distributing inbound tunnel message into our inNetMessagePool: " + msg);
            _context.inNetMessagePool().add(msg, null, null);
        }
    /**
     **** latency measuring attack?
     *        } else if (_context.routerHash().equals(target)) {
     *            // the want to send it to a tunnel, except we are also that tunnel's gateway
     *            // dispatch it directly
     *            if (_log.shouldLog(Log.INFO))
     *                _log.info("distributing inbound tunnel message back out, except we are the gateway");
     *            TunnelGatewayMessage gw = new TunnelGatewayMessage(_context);
     *            gw.setMessage(msg);
     *            gw.setTunnelId(tunnel);
     *            gw.setMessageExpiration(_context.clock().now()+10*1000);
     *            gw.setUniqueId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
     *            _context.tunnelDispatcher().dispatch(gw);
     *****
     */
    } else {
        // ok, they want us to send it remotely, but that'd bust our anonymity,
        // so we send it out a tunnel first
        // TODO use the OCMOSJ cache to pick OB tunnel we are already using?
        TunnelInfo out = _context.tunnelManager().selectOutboundTunnel(_client, target);
        if (out == null) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("no outbound tunnel to send the client message for " + _client + ": " + msg);
            return;
        }
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("distributing IB tunnel msg type " + type + " back out " + out + " targetting " + target);
        TunnelId outId = out.getSendTunnelId(0);
        if (outId == null) {
            if (_log.shouldLog(Log.ERROR))
                _log.error("strange? outbound tunnel has no outboundId? " + out + " failing to distribute " + msg);
            return;
        }
        long exp = _context.clock().now() + 20 * 1000;
        if (msg.getMessageExpiration() < exp)
            msg.setMessageExpiration(exp);
        _context.tunnelDispatcher().dispatchOutbound(msg, outId, tunnel, target);
    }
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) DatabaseStoreMessage(net.i2p.data.i2np.DatabaseStoreMessage) TunnelInfo(net.i2p.router.TunnelInfo) Hash(net.i2p.data.Hash) TunnelId(net.i2p.data.TunnelId)

Example 12 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class TunnelDispatcher method joinInbound.

/**
 * We are the inbound endpoint - we created this tunnel
 *
 *  @return success; false if Tunnel ID is a duplicate
 */
public boolean joinInbound(TunnelCreatorConfig cfg) {
    if (_log.shouldLog(Log.INFO))
        _log.info("Inbound built successfully: " + cfg);
    if (cfg.getLength() > 1) {
        TunnelParticipant participant = new TunnelParticipant(_context, new InboundEndpointProcessor(_context, cfg, _validator));
        TunnelId recvId = cfg.getConfig(cfg.getLength() - 1).getReceiveTunnel();
        if (_participants.putIfAbsent(recvId, participant) != null)
            return false;
        _context.statManager().addRateData("tunnel.joinInboundEndpoint", 1);
        _context.messageHistory().tunnelJoined("inboundEndpoint", cfg);
    } else {
        TunnelGatewayZeroHop gw = new TunnelGatewayZeroHop(_context, cfg);
        TunnelId recvId = cfg.getConfig(0).getReceiveTunnel();
        if (_inboundGateways.putIfAbsent(recvId, gw) != null)
            return false;
        _context.statManager().addRateData("tunnel.joinInboundEndpointZeroHop", 1);
        _context.messageHistory().tunnelJoined("inboundEndpointZeroHop", cfg);
    }
    return true;
}
Also used : TunnelId(net.i2p.data.TunnelId)

Example 13 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class TunnelDispatcher method joinOutboundEndpoint.

/**
 * We are the outbound endpoint in this tunnel, and did not create it
 *
 *  @return success; false if Tunnel ID is a duplicate
 */
public boolean joinOutboundEndpoint(HopConfig cfg) {
    if (_log.shouldLog(Log.INFO))
        _log.info("Joining as OBEP: " + cfg);
    TunnelId recvId = cfg.getReceiveTunnel();
    OutboundTunnelEndpoint endpoint = new OutboundTunnelEndpoint(_context, cfg, new HopProcessor(_context, cfg, _validator));
    synchronized (_joinParticipantLock) {
        if (_participatingConfig.putIfAbsent(recvId, cfg) != null)
            return false;
        if (_outboundEndpoints.putIfAbsent(recvId, endpoint) != null) {
            _participatingConfig.remove(recvId);
            return false;
        }
    }
    _context.messageHistory().tunnelJoined("outboundEndpoint", cfg);
    _context.statManager().addRateData("tunnel.joinOutboundEndpoint", 1);
    if (cfg.getExpiration() > _lastParticipatingExpiration)
        _lastParticipatingExpiration = cfg.getExpiration();
    _leaveJob.add(cfg);
    return true;
}
Also used : TunnelId(net.i2p.data.TunnelId)

Example 14 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class TunnelDispatcher method joinOutbound.

/**
 * We are the outbound gateway - we created this tunnel
 *
 *  @return success; false if Tunnel ID is a duplicate
 */
public boolean joinOutbound(TunnelCreatorConfig cfg) {
    if (_log.shouldLog(Log.INFO))
        _log.info("Outbound built successfully: " + cfg);
    TunnelGateway gw;
    if (cfg.getLength() > 1) {
        TunnelGateway.QueuePreprocessor preproc = createPreprocessor(cfg);
        TunnelGateway.Sender sender = new OutboundSender(_context, cfg);
        TunnelGateway.Receiver receiver = new OutboundReceiver(_context, cfg);
        // TunnelGateway gw = new TunnelGateway(_context, preproc, sender, receiver);
        gw = new PumpedTunnelGateway(_context, preproc, sender, receiver, _pumper);
    } else {
        gw = new TunnelGatewayZeroHop(_context, cfg);
    }
    TunnelId outId = cfg.getConfig(0).getSendTunnel();
    if (_outboundGateways.putIfAbsent(outId, gw) != null)
        return false;
    if (cfg.getLength() > 1) {
        _context.statManager().addRateData("tunnel.joinOutboundGateway", 1);
        _context.messageHistory().tunnelJoined("outbound", cfg);
    } else {
        _context.statManager().addRateData("tunnel.joinOutboundGatewayZeroHop", 1);
        _context.messageHistory().tunnelJoined("outboundZeroHop", cfg);
    }
    return true;
}
Also used : TunnelId(net.i2p.data.TunnelId)

Example 15 with TunnelId

use of net.i2p.data.TunnelId in project i2p.i2p by i2p.

the class PeerTestJob method testPeer.

/**
 * Fire off the necessary jobs and messages to test the given peer
 * The message is a store of the peer's RI to itself,
 * with a reply token.
 */
private void testPeer(RouterInfo peer) {
    TunnelInfo inTunnel = getInboundTunnelId();
    if (inTunnel == null) {
        _log.warn("No tunnels to get peer test replies through!");
        return;
    }
    TunnelId inTunnelId = inTunnel.getReceiveTunnelId(0);
    RouterInfo inGateway = getContext().netDb().lookupRouterInfoLocally(inTunnel.getPeer(0));
    if (inGateway == null) {
        if (_log.shouldLog(Log.WARN))
            _log.warn("We can't find the gateway to our inbound tunnel?! Impossible?");
        return;
    }
    int timeoutMs = getTestTimeout();
    long expiration = getContext().clock().now() + timeoutMs;
    long nonce = 1 + getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE - 1);
    DatabaseStoreMessage msg = buildMessage(peer, inTunnelId, inGateway.getIdentity().getHash(), nonce, expiration);
    TunnelInfo outTunnel = getOutboundTunnelId();
    if (outTunnel == null) {
        _log.warn("No tunnels to send search out through! Something is wrong...");
        return;
    }
    TunnelId outTunnelId = outTunnel.getSendTunnelId(0);
    if (_log.shouldLog(Log.DEBUG))
        _log.debug(getJobId() + ": Sending peer test to " + peer.getIdentity().getHash().toBase64() + " out " + outTunnel + " w/ replies through " + inTunnel);
    ReplySelector sel = new ReplySelector(peer.getIdentity().getHash(), nonce, expiration);
    PeerReplyFoundJob reply = new PeerReplyFoundJob(getContext(), peer, inTunnel, outTunnel);
    PeerReplyTimeoutJob timeoutJob = new PeerReplyTimeoutJob(getContext(), peer, inTunnel, outTunnel, sel);
    getContext().messageRegistry().registerPending(sel, reply, timeoutJob);
    getContext().tunnelDispatcher().dispatchOutbound(msg, outTunnelId, null, peer.getIdentity().getHash());
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) DatabaseStoreMessage(net.i2p.data.i2np.DatabaseStoreMessage) TunnelInfo(net.i2p.router.TunnelInfo) TunnelId(net.i2p.data.TunnelId)

Aggregations

TunnelId (net.i2p.data.TunnelId)33 Hash (net.i2p.data.Hash)20 TunnelInfo (net.i2p.router.TunnelInfo)8 RouterInfo (net.i2p.data.router.RouterInfo)5 DataFormatException (net.i2p.data.DataFormatException)3 LeaseSet (net.i2p.data.LeaseSet)3 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)3 I2NPMessage (net.i2p.data.i2np.I2NPMessage)3 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 Lease (net.i2p.data.Lease)2 DataMessage (net.i2p.data.i2np.DataMessage)2 DeliveryStatusMessage (net.i2p.data.i2np.DeliveryStatusMessage)2 TunnelGatewayMessage (net.i2p.data.i2np.TunnelGatewayMessage)2 Job (net.i2p.router.Job)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 IOException (java.io.IOException)1 TreeSet (java.util.TreeSet)1 SessionKey (net.i2p.data.SessionKey)1