Search in sources :

Example 1 with SmackMessageException

use of org.jivesoftware.smack.SmackException.SmackMessageException in project Smack by igniterealtime.

the class Socks5Client method establish.

/**
 * Initializes the connection to the SOCKS5 proxy by negotiating authentication method and
 * requesting a stream for the given digest. Currently only the no-authentication method is
 * supported by the Socks5Client.
 *
 * @param socket connected to a SOCKS5 proxy
 * @throws IOException if an I/O error occurred.
 * @throws SmackMessageException if there was an error.
 */
protected void establish(Socket socket) throws IOException, SmackMessageException {
    byte[] connectionRequest;
    byte[] connectionResponse;
    /*
         * use DataInputStream/DataOutpuStream to assure read and write is completed in a single
         * statement
         */
    DataInputStream in = new DataInputStream(socket.getInputStream());
    DataOutputStream out = new DataOutputStream(socket.getOutputStream());
    // authentication negotiation
    byte[] cmd = new byte[3];
    // protocol version 5
    cmd[0] = (byte) 0x05;
    // number of authentication methods supported
    cmd[1] = (byte) 0x01;
    // authentication method: no-authentication required
    cmd[2] = (byte) 0x00;
    out.write(cmd);
    out.flush();
    byte[] response = new byte[2];
    in.readFully(response);
    // check if server responded with correct version and no-authentication method
    if (response[0] != (byte) 0x05 || response[1] != (byte) 0x00) {
        throw new SmackException.SmackMessageException("Remote SOCKS5 server responded with unexpected version: " + response[0] + ' ' + response[1] + ". Should be 0x05 0x00.");
    }
    // request SOCKS5 connection with given address/digest
    connectionRequest = createSocks5ConnectRequest();
    out.write(connectionRequest);
    out.flush();
    // receive response
    connectionResponse = Socks5Utils.receiveSocks5Message(in);
    // verify response
    // set expected return status to 0
    connectionRequest[1] = (byte) 0x00;
    if (!Arrays.equals(connectionRequest, connectionResponse)) {
        throw new SmackException.SmackMessageException("Connection request does not equal connection response. Response: " + Arrays.toString(connectionResponse) + ". Request: " + Arrays.toString(connectionRequest));
    }
}
Also used : SmackMessageException(org.jivesoftware.smack.SmackException.SmackMessageException) DataOutputStream(java.io.DataOutputStream) DataInputStream(java.io.DataInputStream)

Example 2 with SmackMessageException

use of org.jivesoftware.smack.SmackException.SmackMessageException in project Smack by igniterealtime.

the class Socks5Client method getSocket.

/**
 * Returns the initialized socket that can be used to transfer data between peers via the SOCKS5
 * proxy.
 *
 * @param timeout timeout to connect to SOCKS5 proxy in milliseconds
 * @return socket the initialized socket
 * @throws IOException if initializing the socket failed due to a network error
 * @throws TimeoutException if connecting to SOCKS5 proxy timed out
 * @throws InterruptedException if the current thread was interrupted while waiting
 * @throws XMPPException if an XMPP protocol error was received.
 * @throws SmackMessageException if there was an error.
 * @throws NotConnectedException if the XMPP connection is not connected.
 * @throws NoResponseException if there was no response from the remote entity.
 */
public Socket getSocket(int timeout) throws IOException, InterruptedException, TimeoutException, XMPPException, SmackMessageException, NotConnectedException, NoResponseException {
    // wrap connecting in future for timeout
    FutureTask<Socket> futureTask = new FutureTask<>(new Callable<Socket>() {

        @Override
        public Socket call() throws IOException, SmackMessageException {
            // initialize socket
            Socket socket = new Socket();
            SocketAddress socketAddress = new InetSocketAddress(streamHost.getAddress().asInetAddress(), streamHost.getPort());
            socket.connect(socketAddress);
            // initialize connection to SOCKS5 proxy
            try {
                establish(socket);
            } catch (SmackMessageException e) {
                if (!socket.isClosed()) {
                    CloseableUtil.maybeClose(socket, LOGGER);
                }
                throw e;
            }
            return socket;
        }
    });
    Async.go(futureTask, "SOCKS5 client connecting to " + streamHost);
    // get connection to initiator with timeout
    try {
        return futureTask.get(timeout, TimeUnit.MILLISECONDS);
    } catch (ExecutionException e) {
        throw new IOException("ExecutionException while SOCKS5 client attempting to connect to " + streamHost, e);
    }
}
Also used : SmackMessageException(org.jivesoftware.smack.SmackException.SmackMessageException) FutureTask(java.util.concurrent.FutureTask) InetSocketAddress(java.net.InetSocketAddress) IOException(java.io.IOException) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) ExecutionException(java.util.concurrent.ExecutionException) Socket(java.net.Socket)

Example 3 with SmackMessageException

use of org.jivesoftware.smack.SmackException.SmackMessageException 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 XMPPException if an XMPP protocol error was received.
 * @throws NotConnectedException if the XMPP connection is not connected.
 * @throws NoResponseException if there was no response from the remote entity.
 * @throws SmackMessageException if there was an error.
 * @throws FeatureNotSupportedException if a requested feature is not supported by the remote entity.
 */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID) throws IOException, InterruptedException, XMPPException, NoResponseException, NotConnectedException, SmackMessageException, FeatureNotSupportedException {
    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.SmackMessageException("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.SmackMessageException("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", e);
    } 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) SmackMessageException(org.jivesoftware.smack.SmackException.SmackMessageException) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) Jid(org.jxmpp.jid.Jid) EntityFullJid(org.jxmpp.jid.EntityFullJid) 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)

Aggregations

SmackMessageException (org.jivesoftware.smack.SmackException.SmackMessageException)3 IOException (java.io.IOException)2 Socket (java.net.Socket)2 DataInputStream (java.io.DataInputStream)1 DataOutputStream (java.io.DataOutputStream)1 InetSocketAddress (java.net.InetSocketAddress)1 SocketAddress (java.net.SocketAddress)1 ArrayList (java.util.ArrayList)1 ExecutionException (java.util.concurrent.ExecutionException)1 FutureTask (java.util.concurrent.FutureTask)1 TimeoutException (java.util.concurrent.TimeoutException)1 FeatureNotSupportedException (org.jivesoftware.smack.SmackException.FeatureNotSupportedException)1 XMPPConnection (org.jivesoftware.smack.XMPPConnection)1 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)1 Stanza (org.jivesoftware.smack.packet.Stanza)1 Bytestream (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream)1 StreamHost (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost)1 StreamHostUsed (org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHostUsed)1 EntityFullJid (org.jxmpp.jid.EntityFullJid)1 Jid (org.jxmpp.jid.Jid)1