Search in sources :

Example 1 with StreamHost

use of org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost in project Smack by igniterealtime.

the class Socks5BytestreamRequest method accept.

/**
     * Accepts the SOCKS5 Bytestream initialization request and returns the socket to send/receive
     * data.
     * <p>
     * Before accepting the SOCKS5 Bytestream request you can set timeouts by invoking
     * {@link #setTotalConnectTimeout(int)} and {@link #setMinimumConnectTimeout(int)}.
     * 
     * @return the socket to send/receive data
     * @throws InterruptedException if the current thread was interrupted while waiting
     * @throws XMPPErrorException 
     * @throws SmackException 
     */
@Override
public Socks5BytestreamSession accept() throws InterruptedException, XMPPErrorException, SmackException {
    Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts();
    // throw exceptions if request contains no stream hosts
    if (streamHosts.size() == 0) {
        cancelRequest();
    }
    StreamHost selectedHost = null;
    Socket socket = null;
    String digest = Socks5Utils.createDigest(this.bytestreamRequest.getSessionID(), this.bytestreamRequest.getFrom(), this.manager.getConnection().getUser());
    /*
         * determine timeout for each connection attempt; each SOCKS5 proxy has the same amount of
         * time so that the first does not consume the whole timeout
         */
    int timeout = Math.max(getTotalConnectTimeout() / streamHosts.size(), getMinimumConnectTimeout());
    for (StreamHost streamHost : streamHosts) {
        String address = streamHost.getAddress() + ":" + streamHost.getPort();
        // check to see if this address has been blacklisted
        int failures = getConnectionFailures(address);
        if (CONNECTION_FAILURE_THRESHOLD > 0 && failures >= CONNECTION_FAILURE_THRESHOLD) {
            continue;
        }
        // establish socket
        try {
            // build SOCKS5 client
            final Socks5Client socks5Client = new Socks5Client(streamHost, digest);
            // connect to SOCKS5 proxy with a timeout
            socket = socks5Client.getSocket(timeout);
            // set selected host
            selectedHost = streamHost;
            break;
        } catch (TimeoutException | IOException | SmackException | XMPPException e) {
            incrementConnectionFailures(address);
        }
    }
    // throw exception if connecting to all SOCKS5 proxies failed
    if (selectedHost == null || socket == null) {
        cancelRequest();
    }
    // send used-host confirmation
    Bytestream response = createUsedHostResponse(selectedHost);
    this.manager.getConnection().sendStanza(response);
    return new Socks5BytestreamSession(socket, selectedHost.getJID().equals(this.bytestreamRequest.getFrom()));
}
Also used : SmackException(org.jivesoftware.smack.SmackException) IOException(java.io.IOException) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) XMPPException(org.jivesoftware.smack.XMPPException) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 2 with StreamHost

use of org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost in project Smack by igniterealtime.

the class BytestreamsProvider method parse.

@Override
public Bytestream parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException {
    boolean done = false;
    Bytestream toReturn = new Bytestream();
    String id = parser.getAttributeValue("", "sid");
    String mode = parser.getAttributeValue("", "mode");
    // streamhost
    Jid JID = null;
    String host = null;
    String port = null;
    int eventType;
    String elementName;
    while (!done) {
        eventType = parser.next();
        elementName = parser.getName();
        if (eventType == XmlPullParser.START_TAG) {
            if (elementName.equals(Bytestream.StreamHost.ELEMENTNAME)) {
                JID = ParserUtils.getJidAttribute(parser);
                host = parser.getAttributeValue("", "host");
                port = parser.getAttributeValue("", "port");
            } else if (elementName.equals(Bytestream.StreamHostUsed.ELEMENTNAME)) {
                toReturn.setUsedHost(ParserUtils.getJidAttribute(parser));
            } else if (elementName.equals(Bytestream.Activate.ELEMENTNAME)) {
                toReturn.setToActivate(ParserUtils.getJidAttribute(parser));
            }
        } else if (eventType == XmlPullParser.END_TAG) {
            if (elementName.equals("streamhost")) {
                if (port == null) {
                    toReturn.addStreamHost(JID, host);
                } else {
                    toReturn.addStreamHost(JID, host, Integer.parseInt(port));
                }
                JID = null;
                host = null;
                port = null;
            } else if (elementName.equals("query")) {
                done = true;
            }
        }
    }
    if (mode == null) {
        toReturn.setMode(Mode.tcp);
    } else {
        toReturn.setMode((Bytestream.Mode.fromName(mode)));
    }
    toReturn.setSessionID(id);
    return toReturn;
}
Also used : Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) Jid(org.jxmpp.jid.Jid)

Example 3 with StreamHost

use of org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost in project Smack by igniterealtime.

the class Socks5BytestreamManager method getLocalStreamHost.

/**
     * Returns the stream host information of the local SOCKS5 proxy containing the IP address and
     * the port or null if local SOCKS5 proxy is not running.
     * 
     * @return the stream host information of the local SOCKS5 proxy or null if local SOCKS5 proxy
     *         is not running
     */
private List<StreamHost> getLocalStreamHost() {
    XMPPConnection connection = connection();
    // get local proxy singleton
    Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy();
    if (!socks5Server.isRunning()) {
        // server is not running
        return null;
    }
    List<String> addresses = socks5Server.getLocalAddresses();
    if (addresses.isEmpty()) {
        // local address could not be determined
        return null;
    }
    final int port = socks5Server.getPort();
    List<StreamHost> streamHosts = new ArrayList<StreamHost>();
    outerloop: for (String address : addresses) {
        // Prevent loopback addresses from appearing as streamhost
        final String[] loopbackAddresses = { "127.0.0.1", "0:0:0:0:0:0:0:1", "::1" };
        for (String loopbackAddress : loopbackAddresses) {
            // ie. the part after the '%' sign.
            if (address.startsWith(loopbackAddress)) {
                continue outerloop;
            }
        }
        streamHosts.add(new StreamHost(connection.getUser(), address, port));
    }
    return streamHosts;
}
Also used : ArrayList(java.util.ArrayList) XMPPConnection(org.jivesoftware.smack.XMPPConnection) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost)

Example 4 with StreamHost

use of org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost in project Smack by igniterealtime.

the class Socks5ByteStreamManagerTest method shouldNotPrioritizeSocks5ProxyIfPrioritizationDisabled.

/**
     * Invoking {@link Socks5BytestreamManager#establishSession(org.jxmpp.jid.Jid, String)} the first time
     * should successfully negotiate a SOCKS5 Bytestream via the second SOCKS5 proxy. The second
     * negotiation should run in the same manner if prioritization is disabled.
     * 
     * @throws Exception should not happen
     */
@Test
public void shouldNotPrioritizeSocks5ProxyIfPrioritizationDisabled() throws Exception {
    // disable clients local SOCKS5 proxy
    Socks5Proxy.setLocalSocks5ProxyEnabled(false);
    // get Socks5ByteStreamManager for connection
    Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
    byteStreamManager.setProxyPrioritizationEnabled(false);
    assertFalse(byteStreamManager.isProxyPrioritizationEnabled());
    Verification<Bytestream, Bytestream> streamHostUsedVerification = new Verification<Bytestream, Bytestream>() {

        @Override
        public void verify(Bytestream request, Bytestream response) {
            assertEquals(response.getSessionID(), request.getSessionID());
            assertEquals(2, request.getStreamHosts().size());
            // verify that the used stream host is the second in list
            StreamHost streamHost = (StreamHost) request.getStreamHosts().toArray()[1];
            assertEquals(response.getUsedHost().getJID(), streamHost.getJID());
        }
    };
    createResponses(streamHostUsedVerification);
    // start a local SOCKS5 proxy
    Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
    socks5Proxy.start();
    // create digest to get the socket opened by target
    String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
    // call the method that should be tested
    OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
    // test the established bytestream
    InputStream inputStream = socks5Proxy.getSocket(digest).getInputStream();
    byte[] data = new byte[] { 1, 2, 3 };
    outputStream.write(data);
    byte[] result = new byte[3];
    inputStream.read(result);
    assertArrayEquals(data, result);
    protocol.verifyAll();
    createResponses(streamHostUsedVerification);
    // call the method that should be tested again
    outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
    // test the established bytestream
    inputStream = socks5Proxy.getSocket(digest).getInputStream();
    outputStream.write(data);
    inputStream.read(result);
    assertArrayEquals(data, result);
    protocol.verifyAll();
    byteStreamManager.setProxyPrioritizationEnabled(true);
}
Also used : Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) Verification(org.jivesoftware.util.Verification) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Test(org.junit.Test)

Example 5 with StreamHost

use of org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost in project Smack by igniterealtime.

the class Socks5ByteStreamManagerTest method shouldUseMultipleAddressesForLocalSocks5Proxy.

/**
     * If multiple network addresses are added to the local SOCKS5 proxy, all of them should be
     * contained in the SOCKS5 Bytestream request.
     * 
     * @throws Exception should not happen
     */
@Test
public void shouldUseMultipleAddressesForLocalSocks5Proxy() throws Exception {
    // enable clients local SOCKS5 proxy on port 7778
    Socks5Proxy.setLocalSocks5ProxyEnabled(true);
    Socks5Proxy.setLocalSocks5ProxyPort(7778);
    // start a local SOCKS5 proxy
    Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
    socks5Proxy.start();
    assertTrue(socks5Proxy.isRunning());
    // get Socks5ByteStreamManager for connection
    Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
    /**
         * create responses in the order they should be queried specified by the XEP-0065
         * specification
         */
    // build discover info that supports the SOCKS5 feature
    DiscoverInfo discoverInfo = Socks5PacketUtils.createDiscoverInfo(targetJID, initiatorJID);
    discoverInfo.addFeature(Bytestream.NAMESPACE);
    // return that SOCKS5 is supported if target is queried
    protocol.addResponse(discoverInfo, Verification.correspondingSenderReceiver, Verification.requestTypeGET);
    // build discover items containing no proxy item
    DiscoverItems discoverItems = Socks5PacketUtils.createDiscoverItems(xmppServer, initiatorJID);
    // return the discover item if XMPP server is queried
    protocol.addResponse(discoverItems, Verification.correspondingSenderReceiver, Verification.requestTypeGET);
    // build used stream host response
    Bytestream streamHostUsedPacket = Socks5PacketUtils.createBytestreamResponse(targetJID, initiatorJID);
    streamHostUsedPacket.setSessionID(sessionID);
    // local proxy used
    streamHostUsedPacket.setUsedHost(initiatorJID);
    // return used stream host info as response to the bytestream initiation
    protocol.addResponse(streamHostUsedPacket, new Verification<Bytestream, Bytestream>() {

        @Override
        public void verify(Bytestream request, Bytestream response) {
            assertEquals(response.getSessionID(), request.getSessionID());
            StreamHost streamHost1 = request.getStreamHosts().get(0);
            assertEquals(response.getUsedHost().getJID(), streamHost1.getJID());
            StreamHost streamHost2 = request.getStreamHosts().get(request.getStreamHosts().size() - 1);
            assertEquals(response.getUsedHost().getJID(), streamHost2.getJID());
            assertEquals("localAddress", streamHost2.getAddress());
        }
    }, Verification.correspondingSenderReceiver, Verification.requestTypeSET);
    // create digest to get the socket opened by target
    String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
    // connect to proxy as target
    socks5Proxy.addTransfer(digest);
    StreamHost streamHost = new StreamHost(targetJID, socks5Proxy.getLocalAddresses().get(0), socks5Proxy.getPort());
    Socks5Client socks5Client = new Socks5Client(streamHost, digest);
    InputStream inputStream = socks5Client.getSocket(2000).getInputStream();
    // add another network address before establishing SOCKS5 Bytestream
    socks5Proxy.addLocalAddress("localAddress");
    // finally call the method that should be tested
    OutputStream outputStream = byteStreamManager.establishSession(targetJID, sessionID).getOutputStream();
    // test the established bytestream
    byte[] data = new byte[] { 1, 2, 3 };
    outputStream.write(data);
    byte[] result = new byte[3];
    inputStream.read(result);
    assertArrayEquals(data, result);
    protocol.verifyAll();
    // reset proxy settings
    socks5Proxy.stop();
    socks5Proxy.removeLocalAddress("localAddress");
    Socks5Proxy.setLocalSocks5ProxyPort(7777);
}
Also used : DiscoverInfo(org.jivesoftware.smackx.disco.packet.DiscoverInfo) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) DiscoverItems(org.jivesoftware.smackx.disco.packet.DiscoverItems) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Test(org.junit.Test)

Aggregations

StreamHost (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost)18 Test (org.junit.Test)13 Bytestream (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream)12 SmackException (org.jivesoftware.smack.SmackException)10 Socket (java.net.Socket)8 InputStream (java.io.InputStream)6 OutputStream (java.io.OutputStream)5 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)5 DataInputStream (java.io.DataInputStream)4 DataOutputStream (java.io.DataOutputStream)4 IOException (java.io.IOException)4 ServerSocket (java.net.ServerSocket)4 XMPPException (org.jivesoftware.smack.XMPPException)4 ArrayList (java.util.ArrayList)3 TimeoutException (java.util.concurrent.TimeoutException)3 FeatureNotSupportedException (org.jivesoftware.smack.SmackException.FeatureNotSupportedException)3 XMPPConnection (org.jivesoftware.smack.XMPPConnection)3 ErrorIQ (org.jivesoftware.smack.packet.ErrorIQ)3 IQ (org.jivesoftware.smack.packet.IQ)3 DiscoverInfo (org.jivesoftware.smackx.disco.packet.DiscoverInfo)3