Search in sources :

Example 6 with Socks5Proxy

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy in project Smack by igniterealtime.

the class Socks5ByteStreamTest method testSocks5BytestreamWithLocalSocks5Proxy.

/**
     * Socks5 bytestream should be successfully established using the local Socks5 proxy.
     * 
     * @throws Exception should not happen
     */
public void testSocks5BytestreamWithLocalSocks5Proxy() throws Exception {
    // setup port for local socks5 proxy
    SmackConfiguration.setLocalSocks5ProxyEnabled(true);
    SmackConfiguration.setLocalSocks5ProxyPort(7778);
    Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
    socks5Proxy.start();
    assertTrue(socks5Proxy.isRunning());
    XMPPConnection initiatorConnection = getConnection(0);
    XMPPConnection targetConnection = getConnection(1);
    // test data
    final byte[] data = new byte[] { 1, 2, 3 };
    final SynchronousQueue<byte[]> queue = new SynchronousQueue<byte[]>();
    Socks5BytestreamManager targetByteStreamManager = Socks5BytestreamManager.getBytestreamManager(targetConnection);
    Socks5BytestreamListener incomingByteStreamListener = new Socks5BytestreamListener() {

        public void incomingBytestreamRequest(Socks5BytestreamRequest request) {
            InputStream inputStream;
            try {
                Socks5BytestreamSession session = request.accept();
                inputStream = session.getInputStream();
                byte[] receivedData = new byte[3];
                inputStream.read(receivedData);
                queue.put(receivedData);
            } catch (Exception e) {
                fail(e.getMessage());
            }
        }
    };
    targetByteStreamManager.addIncomingBytestreamListener(incomingByteStreamListener);
    Socks5BytestreamManager initiatorByteStreamManager = Socks5BytestreamManager.getBytestreamManager(initiatorConnection);
    Socks5BytestreamSession session = initiatorByteStreamManager.establishSession(targetConnection.getUser());
    OutputStream outputStream = session.getOutputStream();
    assertTrue(session.isDirect());
    // verify stream
    outputStream.write(data);
    outputStream.flush();
    outputStream.close();
    assertEquals("received data not equal to sent data", data, queue.take());
    // reset default configuration
    SmackConfiguration.setLocalSocks5ProxyPort(7777);
}
Also used : Socks5BytestreamManager(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamManager) Socks5BytestreamListener(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamListener) Socks5BytestreamRequest(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest) Socks5Proxy(org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy) InputStream(java.io.InputStream) SynchronousQueue(java.util.concurrent.SynchronousQueue) OutputStream(java.io.OutputStream) XMPPConnection(org.jivesoftware.smack.XMPPConnection) TimeoutException(java.util.concurrent.TimeoutException) XMPPException(org.jivesoftware.smack.XMPPException) Socks5BytestreamSession(org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamSession)

Example 7 with Socks5Proxy

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy 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 8 with Socks5Proxy

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy in project Smack by igniterealtime.

the class Socks5BytestreamManager method establishSession.

/**
     * Establishes a SOCKS5 Bytestream with the given user using the given session ID and returns
     * the Socket to send/receive data to/from the user.
     * 
     * @param targetJID the JID of the user a SOCKS5 Bytestream should be established
     * @param sessionID the session ID for the SOCKS5 Bytestream request
     * @return the Socket to send/receive data to/from the user
     * @throws IOException if the bytestream could not be established
     * @throws InterruptedException if the current thread was interrupted while waiting
     * @throws NoResponseException 
     * @throws SmackException if the target does not support SOCKS5.
     * @throws XMPPException 
     */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID) throws IOException, InterruptedException, NoResponseException, SmackException, XMPPException {
    XMPPConnection connection = connection();
    XMPPErrorException discoveryException = null;
    // check if target supports SOCKS5 Bytestream
    if (!supportsSocks5(targetJID)) {
        throw new FeatureNotSupportedException("SOCKS5 Bytestream", targetJID);
    }
    List<Jid> proxies = new ArrayList<>();
    // determine SOCKS5 proxies from XMPP-server
    try {
        proxies.addAll(determineProxies());
    } catch (XMPPErrorException e) {
        // don't abort here, just remember the exception thrown by determineProxies()
        // determineStreamHostInfos() will at least add the local Socks5 proxy (if enabled)
        discoveryException = e;
    }
    // determine address and port of each proxy
    List<StreamHost> streamHosts = determineStreamHostInfos(proxies);
    if (streamHosts.isEmpty()) {
        if (discoveryException != null) {
            throw discoveryException;
        } else {
            throw new SmackException("no SOCKS5 proxies available");
        }
    }
    // compute digest
    String digest = Socks5Utils.createDigest(sessionID, connection.getUser(), targetJID);
    // prioritize last working SOCKS5 proxy if exists
    if (this.proxyPrioritizationEnabled && this.lastWorkingProxy != null) {
        StreamHost selectedStreamHost = null;
        for (StreamHost streamHost : streamHosts) {
            if (streamHost.getJID().equals(this.lastWorkingProxy)) {
                selectedStreamHost = streamHost;
                break;
            }
        }
        if (selectedStreamHost != null) {
            streamHosts.remove(selectedStreamHost);
            streamHosts.add(0, selectedStreamHost);
        }
    }
    Socks5Proxy socks5Proxy = Socks5Proxy.getSocks5Proxy();
    try {
        // add transfer digest to local proxy to make transfer valid
        socks5Proxy.addTransfer(digest);
        // create initiation packet
        Bytestream initiation = createBytestreamInitiation(sessionID, targetJID, streamHosts);
        // send initiation packet
        Stanza response = connection.createStanzaCollectorAndSend(initiation).nextResultOrThrow(getTargetResponseTimeout());
        // extract used stream host from response
        StreamHostUsed streamHostUsed = ((Bytestream) response).getUsedHost();
        StreamHost usedStreamHost = initiation.getStreamHost(streamHostUsed.getJID());
        if (usedStreamHost == null) {
            throw new SmackException("Remote user responded with unknown host");
        }
        // build SOCKS5 client
        Socks5Client socks5Client = new Socks5ClientForInitiator(usedStreamHost, digest, connection, sessionID, targetJID);
        // establish connection to proxy
        Socket socket = socks5Client.getSocket(getProxyConnectionTimeout());
        // remember last working SOCKS5 proxy to prioritize it for next request
        this.lastWorkingProxy = usedStreamHost.getJID();
        // negotiation successful, return the output stream
        return new Socks5BytestreamSession(socket, usedStreamHost.getJID().equals(connection.getUser()));
    } catch (TimeoutException e) {
        throw new IOException("Timeout while connecting to SOCKS5 proxy");
    } finally {
        // remove transfer digest if output stream is returned or an exception
        // occurred
        socks5Proxy.removeTransfer(digest);
    }
}
Also used : StreamHostUsed(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHostUsed) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) Jid(org.jxmpp.jid.Jid) SmackException(org.jivesoftware.smack.SmackException) Stanza(org.jivesoftware.smack.packet.Stanza) FeatureNotSupportedException(org.jivesoftware.smack.SmackException.FeatureNotSupportedException) ArrayList(java.util.ArrayList) XMPPConnection(org.jivesoftware.smack.XMPPConnection) IOException(java.io.IOException) Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) StreamHost(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost) Socket(java.net.Socket) TimeoutException(java.util.concurrent.TimeoutException)

Example 9 with Socks5Proxy

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy in project Smack by igniterealtime.

the class Socks5ByteStreamRequestTest method shouldAcceptSocks5BytestreamRequestAndReceiveData.

/**
     * Accepting the SOCKS5 Bytestream request should be successfully.
     * 
     * @throws Exception should not happen
     */
@Test
public void shouldAcceptSocks5BytestreamRequestAndReceiveData() throws Exception {
    // start a local SOCKS5 proxy
    Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7778);
    // build SOCKS5 Bytestream initialization request
    Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(initiatorJID, targetJID, sessionID);
    bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7778);
    // create test data for stream
    byte[] data = new byte[] { 1, 2, 3 };
    // get SOCKS5 Bytestream manager for connection
    Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
    // build SOCKS5 Bytestream request with the bytestream initialization
    Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager, bytestreamInitialization);
    // accept the stream (this is the call that is tested here)
    InputStream inputStream = byteStreamRequest.accept().getInputStream();
    // create digest to get the socket opened by target
    String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
    // test stream by sending some data
    OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
    outputStream.write(data);
    // verify that data is transferred correctly
    byte[] result = new byte[3];
    inputStream.read(result);
    assertArrayEquals(data, result);
    // verify targets response
    assertEquals(1, protocol.getRequests().size());
    Stanza targetResponse = protocol.getRequests().remove(0);
    assertEquals(Bytestream.class, targetResponse.getClass());
    assertEquals(initiatorJID, targetResponse.getTo());
    assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
    assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
}
Also used : Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) Stanza(org.jivesoftware.smack.packet.Stanza) Test(org.junit.Test)

Example 10 with Socks5Proxy

use of org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy in project Smack by igniterealtime.

the class Socks5ByteStreamRequestTest method shouldBlacklistInvalidProxyAfter2Failures.

/**
     * Target should not try to connect to SOCKS5 proxies that already failed twice.
     * 
     * @throws Exception should not happen
     */
@Test
public void shouldBlacklistInvalidProxyAfter2Failures() throws Exception {
    // build SOCKS5 Bytestream initialization request
    Bytestream bytestreamInitialization = Socks5PacketUtils.createBytestreamInitiation(initiatorJID, targetJID, sessionID);
    bytestreamInitialization.addStreamHost(JidCreate.from("invalid." + proxyJID), "127.0.0.2", 7778);
    // get SOCKS5 Bytestream manager for connection
    Socks5BytestreamManager byteStreamManager = Socks5BytestreamManager.getBytestreamManager(connection);
    // try to connect several times
    for (int i = 0; i < 2; i++) {
        try {
            // build SOCKS5 Bytestream request with the bytestream initialization
            Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager, bytestreamInitialization);
            // set timeouts
            byteStreamRequest.setTotalConnectTimeout(600);
            byteStreamRequest.setMinimumConnectTimeout(300);
            // accept the stream (this is the call that is tested here)
            byteStreamRequest.accept();
            fail("exception should be thrown");
        } catch (XMPPErrorException e) {
            assertTrue(e.getXMPPError().getDescriptiveText("en").contains("Could not establish socket with any provided host"));
        }
        // verify targets response
        assertEquals(1, protocol.getRequests().size());
        Stanza targetResponse = protocol.getRequests().remove(0);
        assertTrue(IQ.class.isInstance(targetResponse));
        assertEquals(initiatorJID, targetResponse.getTo());
        assertEquals(IQ.Type.error, ((IQ) targetResponse).getType());
        assertEquals(XMPPError.Condition.item_not_found, ((IQ) targetResponse).getError().getCondition());
    }
    // create test data for stream
    byte[] data = new byte[] { 1, 2, 3 };
    Socks5TestProxy socks5Proxy = Socks5TestProxy.getProxy(7779);
    assertTrue(socks5Proxy.isRunning());
    // add a valid SOCKS5 proxy
    bytestreamInitialization.addStreamHost(proxyJID, proxyAddress, 7779);
    // build SOCKS5 Bytestream request with the bytestream initialization
    Socks5BytestreamRequest byteStreamRequest = new Socks5BytestreamRequest(byteStreamManager, bytestreamInitialization);
    // set timeouts
    byteStreamRequest.setTotalConnectTimeout(600);
    byteStreamRequest.setMinimumConnectTimeout(300);
    // accept the stream (this is the call that is tested here)
    InputStream inputStream = byteStreamRequest.accept().getInputStream();
    // create digest to get the socket opened by target
    String digest = Socks5Utils.createDigest(sessionID, initiatorJID, targetJID);
    // test stream by sending some data
    OutputStream outputStream = socks5Proxy.getSocket(digest).getOutputStream();
    outputStream.write(data);
    // verify that data is transferred correctly
    byte[] result = new byte[3];
    inputStream.read(result);
    assertArrayEquals(data, result);
    // verify targets response
    assertEquals(1, protocol.getRequests().size());
    Stanza targetResponse = protocol.getRequests().remove(0);
    assertEquals(Bytestream.class, targetResponse.getClass());
    assertEquals(initiatorJID, targetResponse.getTo());
    assertEquals(IQ.Type.result, ((Bytestream) targetResponse).getType());
    assertEquals(proxyJID, ((Bytestream) targetResponse).getUsedHost().getJID());
}
Also used : Bytestream(org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) InputStream(java.io.InputStream) Stanza(org.jivesoftware.smack.packet.Stanza) OutputStream(java.io.OutputStream) IQ(org.jivesoftware.smack.packet.IQ) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)11 InputStream (java.io.InputStream)10 StreamHost (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost)10 OutputStream (java.io.OutputStream)9 Bytestream (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream)9 Socket (java.net.Socket)4 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)4 IQ (org.jivesoftware.smack.packet.IQ)4 Stanza (org.jivesoftware.smack.packet.Stanza)4 SmackException (org.jivesoftware.smack.SmackException)3 XMPPConnection (org.jivesoftware.smack.XMPPConnection)3 ErrorIQ (org.jivesoftware.smack.packet.ErrorIQ)3 ArrayList (java.util.ArrayList)2 TimeoutException (java.util.concurrent.TimeoutException)2 XMPPException (org.jivesoftware.smack.XMPPException)2 EmptyResultIQ (org.jivesoftware.smack.packet.EmptyResultIQ)2 DiscoverInfo (org.jivesoftware.smackx.disco.packet.DiscoverInfo)2 DiscoverItems (org.jivesoftware.smackx.disco.packet.DiscoverItems)2 Verification (org.jivesoftware.util.Verification)2 IOException (java.io.IOException)1