1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-26 13:24:49 +02:00
Smack/extensions/src/test/java/org/jivesoftware/smackx/bytestreams/socks5/Socks5ClientTest.java
Florian Schmaus 4b56446e40 Introduce SmackException
SmackException (and it's subclasses) is for all errors/exceptions not
defined by any XMPP specification. XMPPException is now an abstract
class for all errors defined by the XMPP specifications.

Methods that involve an IQ exchange now either return the result, which
is obtained by IQ response, or they throw an XMPPErrorException if an IQ
error was the result of the IQ set/get. If there was no response from
the server within the default packet timeout, a NoResponseException will
be thrown.

XMPP SASL errors are now also reported accordingly.

SMACK-426
2014-03-14 01:46:42 +01:00

336 lines
11 KiB
Java

/**
*
* Copyright the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.bytestreams.socks5;
import static org.junit.Assert.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Client;
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Utils;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test for Socks5Client class.
*
* @author Henning Staib
*/
public class Socks5ClientTest {
// settings
private String serverAddress = "127.0.0.1";
private int serverPort = 7890;
private String proxyJID = "proxy.xmpp-server";
private String digest = "digest";
private ServerSocket serverSocket;
/**
* Initialize fields used in the tests.
*
* @throws Exception should not happen
*/
@Before
public void setup() throws Exception {
// create SOCKS5 proxy server socket
serverSocket = new ServerSocket(serverPort);
}
/**
* A SOCKS5 client MUST close connection if server doesn't accept any of the given
* authentication methods. (See RFC1928 Section 3)
*
* @throws Exception should not happen
*/
@Test
public void shouldCloseSocketIfServerDoesNotAcceptAuthenticationMethod() throws Exception {
// start thread to connect to SOCKS5 proxy
Thread serverThread = new Thread() {
@Override
public void run() {
StreamHost streamHost = new StreamHost(proxyJID, serverAddress);
streamHost.setPort(serverPort);
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
try {
socks5Client.getSocket(10000);
fail("exception should be thrown");
}
catch (SmackException e) {
assertTrue(e.getMessage().contains(
"SOCKS5 negotiation failed"));
}
catch (Exception e) {
fail(e.getMessage());
}
}
};
serverThread.start();
// accept connection form client
Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// validate authentication request
assertEquals((byte) 0x05, (byte) in.read()); // version
assertEquals((byte) 0x01, (byte) in.read()); // number of supported auth methods
assertEquals((byte) 0x00, (byte) in.read()); // no-authentication method
// respond that no authentication method is accepted
out.write(new byte[] { (byte) 0x05, (byte) 0xFF });
out.flush();
// wait for client to shutdown
serverThread.join();
// assert socket is closed
assertEquals(-1, in.read());
}
/**
* The SOCKS5 client should close connection if server replies in an unsupported way.
*
* @throws Exception should not happen
*/
@Test
public void shouldCloseSocketIfServerRepliesInUnsupportedWay() throws Exception {
// start thread to connect to SOCKS5 proxy
Thread serverThread = new Thread() {
@Override
public void run() {
StreamHost streamHost = new StreamHost(proxyJID, serverAddress);
streamHost.setPort(serverPort);
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
try {
socks5Client.getSocket(10000);
fail("exception should be thrown");
}
catch (SmackException e) {
assertTrue(e.getMessage().contains(
"Unsupported SOCKS5 address type"));
}
catch (Exception e) {
fail(e.getMessage());
}
}
};
serverThread.start();
// accept connection from client
Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// validate authentication request
assertEquals((byte) 0x05, (byte) in.read()); // version
assertEquals((byte) 0x01, (byte) in.read()); // number of supported auth methods
assertEquals((byte) 0x00, (byte) in.read()); // no-authentication method
// respond that no no-authentication method is used
out.write(new byte[] { (byte) 0x05, (byte) 0x00 });
out.flush();
Socks5Utils.receiveSocks5Message(in);
// reply with unsupported address type
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00 });
out.flush();
// wait for client to shutdown
serverThread.join();
// assert socket is closed
assertEquals(-1, in.read());
}
/**
* The SOCKS5 client should close connection if server replies with an error.
*
* @throws Exception should not happen
*/
@Test
public void shouldCloseSocketIfServerRepliesWithError() throws Exception {
// start thread to connect to SOCKS5 proxy
Thread serverThread = new Thread() {
@Override
public void run() {
StreamHost streamHost = new StreamHost(proxyJID, serverAddress);
streamHost.setPort(serverPort);
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
try {
socks5Client.getSocket(10000);
fail("exception should be thrown");
}
catch (SmackException e) {
assertTrue(e.getMessage().contains(
"SOCKS5 negotiation failed"));
}
catch (Exception e) {
fail(e.getMessage());
}
}
};
serverThread.start();
Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// validate authentication request
assertEquals((byte) 0x05, (byte) in.read()); // version
assertEquals((byte) 0x01, (byte) in.read()); // number of supported auth methods
assertEquals((byte) 0x00, (byte) in.read()); // no-authentication method
// respond that no no-authentication method is used
out.write(new byte[] { (byte) 0x05, (byte) 0x00 });
out.flush();
Socks5Utils.receiveSocks5Message(in);
// reply with full SOCKS5 message with an error code (01 = general SOCKS server
// failure)
out.write(new byte[] { (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x03 });
byte[] address = digest.getBytes();
out.write(address.length);
out.write(address);
out.write(new byte[] { (byte) 0x00, (byte) 0x00 });
out.flush();
// wait for client to shutdown
serverThread.join();
// assert socket is closed
assertEquals(-1, in.read());
}
/**
* The SOCKS5 client should successfully connect to the SOCKS5 server
*
* @throws Exception should not happen
*/
@Test
public void shouldSuccessfullyConnectToSocks5Server() throws Exception {
// start thread to connect to SOCKS5 proxy
Thread serverThread = new Thread() {
@Override
public void run() {
StreamHost streamHost = new StreamHost(proxyJID, serverAddress);
streamHost.setPort(serverPort);
Socks5Client socks5Client = new Socks5Client(streamHost, digest);
try {
Socket socket = socks5Client.getSocket(10000);
assertNotNull(socket);
socket.getOutputStream().write(123);
socket.close();
}
catch (Exception e) {
fail(e.getMessage());
}
}
};
serverThread.start();
Socket socket = serverSocket.accept();
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// validate authentication request
assertEquals((byte) 0x05, (byte) in.read()); // version
assertEquals((byte) 0x01, (byte) in.read()); // number of supported auth methods
assertEquals((byte) 0x00, (byte) in.read()); // no-authentication method
// respond that no no-authentication method is used
out.write(new byte[] { (byte) 0x05, (byte) 0x00 });
out.flush();
byte[] address = digest.getBytes();
assertEquals((byte) 0x05, (byte) in.read()); // version
assertEquals((byte) 0x01, (byte) in.read()); // connect request
assertEquals((byte) 0x00, (byte) in.read()); // reserved byte (always 0)
assertEquals((byte) 0x03, (byte) in.read()); // address type (domain)
assertEquals(address.length, (byte) in.read()); // address length
for (int i = 0; i < address.length; i++) {
assertEquals(address[i], (byte) in.read()); // address
}
assertEquals((byte) 0x00, (byte) in.read()); // port
assertEquals((byte) 0x00, (byte) in.read());
// reply with success SOCKS5 message
out.write(new byte[] { (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x03 });
out.write(address.length);
out.write(address);
out.write(new byte[] { (byte) 0x00, (byte) 0x00 });
out.flush();
// wait for client to shutdown
serverThread.join();
// verify data sent from client
assertEquals(123, in.read());
// assert socket is closed
assertEquals(-1, in.read());
}
/**
* Close fake SOCKS5 proxy.
*
* @throws Exception should not happen
*/
@After
public void cleanup() throws Exception {
serverSocket.close();
}
}