Search in sources :

Example 1 with DataFormatException

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

the class Packet method readPacket.

/**
 * Read the packet from the buffer (starting at the offset) and return
 * the number of bytes read.
 *
 * @param buffer packet buffer containing the data
 * @param offset index into the buffer to start readign
 * @param length how many bytes within the buffer past the offset are
 *               part of the packet?
 *
 * @throws IllegalArgumentException if the data is b0rked
 */
public void readPacket(byte[] buffer, int offset, int length) throws IllegalArgumentException {
    if (buffer.length - offset < length)
        throw new IllegalArgumentException("len=" + buffer.length + " off=" + offset + " length=" + length);
    if (// min header size
    length < 22)
        throw new IllegalArgumentException("Too small: len=" + buffer.length);
    int cur = offset;
    setSendStreamId(DataHelper.fromLong(buffer, cur, 4));
    cur += 4;
    setReceiveStreamId(DataHelper.fromLong(buffer, cur, 4));
    cur += 4;
    setSequenceNum(DataHelper.fromLong(buffer, cur, 4));
    cur += 4;
    setAckThrough(DataHelper.fromLong(buffer, cur, 4));
    cur += 4;
    int numNacks = buffer[cur] & 0xff;
    cur++;
    if (length < 22 + numNacks * 4)
        throw new IllegalArgumentException("Too small with " + numNacks + " nacks: " + length);
    if (numNacks > 0) {
        long[] nacks = new long[numNacks];
        for (int i = 0; i < numNacks; i++) {
            nacks[i] = DataHelper.fromLong(buffer, cur, 4);
            cur += 4;
        }
        setNacks(nacks);
    } else {
        setNacks(null);
    }
    setResendDelay(buffer[cur] & 0xff);
    cur++;
    setFlags((int) DataHelper.fromLong(buffer, cur, 2));
    cur += 2;
    int optionSize = (int) DataHelper.fromLong(buffer, cur, 2);
    cur += 2;
    if (length < 22 + numNacks * 4 + optionSize)
        throw new IllegalArgumentException("Too small with " + numNacks + " nacks and " + optionSize + " options: " + length);
    int payloadBegin = cur + optionSize;
    int payloadSize = length - payloadBegin;
    if ((payloadSize < 0) || (payloadSize > MAX_PAYLOAD_SIZE))
        throw new IllegalArgumentException("length: " + length + " offset: " + offset + " begin: " + payloadBegin);
    // skip ahead to the payload
    // _payload = new ByteArray(new byte[payloadSize]);
    _payload = new ByteArray(buffer, payloadBegin, payloadSize);
    // ok now lets go back and deal with the options
    if (isFlagSet(FLAG_DELAY_REQUESTED)) {
        setOptionalDelay((int) DataHelper.fromLong(buffer, cur, 2));
        cur += 2;
    }
    if (isFlagSet(FLAG_FROM_INCLUDED)) {
        ByteArrayInputStream bais = new ByteArrayInputStream(buffer, cur, length - cur);
        try {
            Destination optionFrom = Destination.create(bais);
            cur += optionFrom.size();
            _optionFrom = optionFrom;
        } catch (IOException ioe) {
            throw new IllegalArgumentException("Bad from field", ioe);
        } catch (DataFormatException dfe) {
            throw new IllegalArgumentException("Bad from field", dfe);
        }
    }
    if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED)) {
        setOptionalMaxSize((int) DataHelper.fromLong(buffer, cur, 2));
        cur += 2;
    }
    if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
        Signature optionSignature;
        Destination from = getOptionalFrom();
        if (from != null) {
            optionSignature = new Signature(from.getSigningPublicKey().getType());
        } else {
            // super cheat for now, look for correct type,
            // assume no more options. If we add to the options
            // we will have to ask the manager.
            // We will get this wrong for Ed25519, same length as P256...
            // See verifySignature() below where we will recast the signature to
            // the correct type if necessary
            int siglen = payloadBegin - cur;
            SigType type = null;
            for (SigType t : SigType.values()) {
                if (t.getSigLen() == siglen) {
                    type = t;
                    break;
                }
            }
            if (type == null) {
                if (siglen < Signature.SIGNATURE_BYTES)
                    throw new IllegalArgumentException("unknown sig type len=" + siglen);
                // Hope it's the default type with some unknown options following;
                // if not the sig will fail later
                type = SigType.DSA_SHA1;
                siglen = Signature.SIGNATURE_BYTES;
            }
            optionSignature = new Signature(type);
        }
        byte[] buf = new byte[optionSignature.length()];
        System.arraycopy(buffer, cur, buf, 0, buf.length);
        optionSignature.setData(buf);
        setOptionalSignature(optionSignature);
        cur += buf.length;
    }
}
Also used : Destination(net.i2p.data.Destination) DataFormatException(net.i2p.data.DataFormatException) ByteArrayInputStream(java.io.ByteArrayInputStream) Signature(net.i2p.data.Signature) ByteArray(net.i2p.data.ByteArray) IOException(java.io.IOException) SigType(net.i2p.crypto.SigType)

Example 2 with DataFormatException

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

the class SAMv1Handler method execNamingMessage.

/* Parse and execute a NAMING message */
protected boolean execNamingMessage(String opcode, Properties props) {
    if (opcode.equals("LOOKUP")) {
        String name = props.getProperty("NAME");
        if (name == null) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Name to resolve not specified in NAMING message");
            return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND NAME=\"\" MESSAGE=\"Must specify NAME\"\n");
        }
        Destination dest = null;
        if (name.equals("ME")) {
            if (rawSession != null) {
                dest = rawSession.getDestination();
            } else if (streamSession != null) {
                dest = streamSession.getDestination();
            } else if (datagramSession != null) {
                dest = datagramSession.getDestination();
            } else {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Lookup for SESSION destination, but session is null");
                return false;
            }
        } else {
            try {
                dest = SAMUtils.getDest(name);
            } catch (DataFormatException e) {
            }
        }
        if (dest == null) {
            return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND NAME=" + name + "\n");
        }
        return writeString("NAMING REPLY RESULT=OK NAME=" + name + " VALUE=" + dest.toBase64() + "\n");
    } else {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("Unrecognized NAMING message opcode: \"" + opcode + "\"");
        return false;
    }
}
Also used : Destination(net.i2p.data.Destination) DataFormatException(net.i2p.data.DataFormatException)

Example 3 with DataFormatException

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

the class SAMv1Handler method execSessionMessage.

/* Parse and execute a SESSION message */
protected boolean execSessionMessage(String opcode, Properties props) {
    String dest = "BUG!";
    try {
        if (opcode.equals("CREATE")) {
            if ((rawSession != null) || (datagramSession != null) || (streamSession != null)) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Trying to create a session, but one still exists");
                return writeString(SESSION_ERROR, "Session already exists");
            }
            if (props.isEmpty()) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("No parameters specified in SESSION CREATE message");
                return writeString(SESSION_ERROR, "No parameters for SESSION CREATE");
            }
            dest = (String) props.remove("DESTINATION");
            if (dest == null) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("SESSION DESTINATION parameter not specified");
                return writeString(SESSION_ERROR, "DESTINATION not specified");
            }
            String destKeystream = null;
            if (dest.equals("TRANSIENT")) {
                _log.debug("TRANSIENT destination requested");
                ByteArrayOutputStream priv = new ByteArrayOutputStream(640);
                SAMUtils.genRandomKey(priv, null);
                destKeystream = Base64.encode(priv.toByteArray());
            } else {
                destKeystream = bridge.getKeystream(dest);
                if (destKeystream == null) {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Custom destination specified [" + dest + "] but it isn't known, creating a new one");
                    ByteArrayOutputStream baos = new ByteArrayOutputStream(640);
                    SAMUtils.genRandomKey(baos, null);
                    destKeystream = Base64.encode(baos.toByteArray());
                    bridge.addKeystream(dest, destKeystream);
                } else {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Custom destination specified [" + dest + "] and it is already known");
                }
            }
            String style = (String) props.remove("STYLE");
            if (style == null) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("SESSION STYLE parameter not specified");
                return writeString(SESSION_ERROR, "No SESSION STYLE specified");
            }
            // Unconditionally override what the client may have set
            // (iMule sets BestEffort) as None is more efficient
            // and the client has no way to access delivery notifications
            props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
            if (style.equals("RAW")) {
                rawSession = new SAMRawSession(destKeystream, props, this);
                rawSession.start();
            } else if (style.equals("DATAGRAM")) {
                datagramSession = new SAMDatagramSession(destKeystream, props, this);
                datagramSession.start();
            } else if (style.equals("STREAM")) {
                String dir = (String) props.remove("DIRECTION");
                if (dir == null) {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("No DIRECTION parameter in STREAM session, defaulting to BOTH");
                    dir = "BOTH";
                } else if (!dir.equals("CREATE") && !dir.equals("RECEIVE") && !dir.equals("BOTH")) {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug("Unknown DIRECTION parameter value: [" + dir + "]");
                    return writeString(SESSION_ERROR, "Unknown DIRECTION parameter");
                }
                streamSession = newSAMStreamSession(destKeystream, dir, props);
                streamSession.start();
            } else {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug("Unrecognized SESSION STYLE: \"" + style + "\"");
                return writeString(SESSION_ERROR, "Unrecognized SESSION STYLE");
            }
            return writeString("SESSION STATUS RESULT=OK DESTINATION=" + dest + "\n");
        } else {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug("Unrecognized SESSION message opcode: \"" + opcode + "\"");
            return writeString(SESSION_ERROR, "Unrecognized opcode");
        }
    } catch (DataFormatException e) {
        _log.error("Invalid SAM destination specified", e);
        return writeString("SESSION STATUS RESULT=INVALID_KEY", e.getMessage());
    } catch (I2PSessionException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    } catch (SAMException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    } catch (IOException e) {
        _log.error("Failed to start SAM session", e);
        return writeString(SESSION_ERROR, e.getMessage());
    }
}
Also used : DataFormatException(net.i2p.data.DataFormatException) I2PSessionException(net.i2p.client.I2PSessionException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) InterruptedIOException(java.io.InterruptedIOException)

Example 4 with DataFormatException

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

the class SAMDatagramSession method messageReceived.

protected void messageReceived(byte[] msg, int proto, int fromPort, int toPort) {
    byte[] payload;
    Destination sender;
    try {
        synchronized (dgramDissector) {
            dgramDissector.loadI2PDatagram(msg);
            sender = dgramDissector.getSender();
            payload = dgramDissector.extractPayload();
        }
    } catch (DataFormatException e) {
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug("Dropping ill-formatted I2P repliable datagram", e);
        }
        return;
    } catch (I2PInvalidDatagramException e) {
        if (_log.shouldLog(Log.DEBUG)) {
            _log.debug("Dropping ill-signed I2P repliable datagram", e);
        }
        return;
    }
    try {
        recv.receiveDatagramBytes(sender, payload, proto, fromPort, toPort);
    } catch (IOException e) {
        _log.error("Error forwarding message to receiver", e);
        close();
    }
}
Also used : Destination(net.i2p.data.Destination) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException) I2PInvalidDatagramException(net.i2p.client.datagram.I2PInvalidDatagramException)

Example 5 with DataFormatException

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

the class SAMUtils method getDest.

/**
 * Resolve the destination from a key or a hostname
 *
 * @param s Hostname or key to be resolved
 *
 * @return the Destination for the specified hostname, non-null
 * @throws DataFormatException on bad Base 64 or name not found
 */
public static Destination getDest(String s) throws DataFormatException {
    // NamingService caches b64 so just use it for everything
    // TODO: Add a static local cache here so SAM doesn't flush the
    // NamingService cache
    Destination d = lookupHost(s);
    if (d == null) {
        String msg;
        if (s.length() >= 516)
            msg = "Bad Base64 dest: ";
        else if (s.length() == 60 && s.endsWith(".b32.i2p"))
            msg = "Lease set not found: ";
        else
            msg = "Host name not found: ";
        throw new DataFormatException(msg + s);
    }
    return d;
}
Also used : Destination(net.i2p.data.Destination) DataFormatException(net.i2p.data.DataFormatException)

Aggregations

DataFormatException (net.i2p.data.DataFormatException)112 IOException (java.io.IOException)53 Destination (net.i2p.data.Destination)32 Properties (java.util.Properties)19 ByteArrayOutputStream (java.io.ByteArrayOutputStream)17 FileInputStream (java.io.FileInputStream)16 Hash (net.i2p.data.Hash)14 File (java.io.File)13 SigType (net.i2p.crypto.SigType)13 I2PSessionException (net.i2p.client.I2PSessionException)12 InputStream (java.io.InputStream)11 PrivateKey (net.i2p.data.PrivateKey)11 SigningPrivateKey (net.i2p.data.SigningPrivateKey)11 SigningPublicKey (net.i2p.data.SigningPublicKey)11 RouterInfo (net.i2p.data.router.RouterInfo)11 Signature (net.i2p.data.Signature)10 FileOutputStream (java.io.FileOutputStream)8 InterruptedIOException (java.io.InterruptedIOException)8 HashMap (java.util.HashMap)8 PublicKey (net.i2p.data.PublicKey)8