0
|
1 package net.sourceforge.jsocks;
|
|
2 import java.io.DataInputStream;
|
|
3 import java.io.IOException;
|
|
4 import java.io.InputStream;
|
|
5 import java.io.OutputStream;
|
|
6 import java.net.InetAddress;
|
|
7 import java.net.UnknownHostException;
|
|
8
|
|
9 /**
|
|
10 SOCKS4 Reply/Request message.
|
|
11 */
|
|
12
|
|
13 public class Socks4Message extends ProxyMessage {
|
|
14
|
|
15 private byte[] msgBytes;
|
|
16 private int msgLength;
|
|
17
|
|
18 /**
|
|
19 * Server failed reply, cmd command for failed request
|
|
20 */
|
|
21 public Socks4Message(int cmd) {
|
|
22 super(cmd, null, 0);
|
|
23 this.user = null;
|
|
24 msgLength = 2;
|
|
25 msgBytes = new byte[2];
|
|
26 msgBytes[0] = (byte) 0;
|
|
27 msgBytes[1] = (byte) command;
|
|
28 }
|
|
29
|
|
30 /**
|
|
31 * Server successfull reply
|
|
32 */
|
|
33 public Socks4Message(int cmd, InetAddress ip, int port) {
|
|
34 this(0, cmd, ip, port, null);
|
|
35 }
|
|
36
|
|
37 /**
|
|
38 * Client request
|
|
39 */
|
|
40 public Socks4Message(int cmd, InetAddress ip, int port, String user) {
|
|
41 this(SOCKS_VERSION, cmd, ip, port, user);
|
|
42 }
|
|
43
|
|
44 /**
|
|
45 * Most general constructor
|
|
46 */
|
|
47 public Socks4Message(int version, int cmd,
|
|
48 InetAddress ip, int port, String user) {
|
|
49 super(cmd, ip, port);
|
|
50 this.user = user;
|
|
51 this.version = version;
|
|
52 msgLength = user == null ? 8 : 9 + user.length();
|
|
53 msgBytes = new byte[msgLength];
|
|
54 msgBytes[0] = (byte) version;
|
|
55 msgBytes[1] = (byte) command;
|
|
56 msgBytes[2] = (byte)(port >> 8);
|
|
57 msgBytes[3] = (byte) port;
|
|
58 byte[] addr;
|
|
59
|
|
60 if (ip != null)
|
|
61 addr = ip.getAddress();
|
|
62 else {
|
|
63 addr = new byte[4];
|
|
64 addr[0] = addr[1] = addr[2] = addr[3] = 0;
|
|
65 }
|
|
66
|
|
67 System.arraycopy(addr, 0, msgBytes, 4, 4);
|
|
68
|
|
69 if (user != null) {
|
|
70 byte[] buf = user.getBytes();
|
|
71 System.arraycopy(buf, 0, msgBytes, 8, buf.length);
|
|
72 msgBytes[msgBytes.length - 1 ] = 0;
|
|
73 }
|
|
74 }
|
|
75
|
|
76 /**
|
|
77 *Initialise from the stream
|
|
78 *If clientMode is true attempts to read a server response
|
|
79 *otherwise reads a client request
|
|
80 *see read for more detail
|
|
81 */
|
|
82 public Socks4Message(InputStream in, boolean clientMode) throws IOException {
|
|
83 msgBytes = null;
|
|
84 read(in, clientMode);
|
|
85 }
|
|
86
|
|
87 @Override
|
|
88 public void read(InputStream in) throws IOException {
|
|
89 read(in, true);
|
|
90 }
|
|
91
|
|
92 @Override
|
|
93 public void read(InputStream in, boolean clientMode) throws IOException {
|
|
94 boolean mode4a = false;
|
|
95 DataInputStream d_in = new DataInputStream(in);
|
|
96 version = d_in.readUnsignedByte();
|
|
97 command = d_in.readUnsignedByte();
|
|
98
|
|
99 if (clientMode && command != REPLY_OK) {
|
|
100 String errMsg;
|
|
101
|
|
102 if (command > REPLY_OK && command < REPLY_BAD_IDENTD)
|
|
103 errMsg = replyMessage[command - REPLY_OK];
|
|
104 else
|
|
105 errMsg = "Unknown Reply Code";
|
|
106
|
|
107 throw new SocksException(command, errMsg);
|
|
108 }
|
|
109
|
|
110 port = d_in.readUnsignedShort();
|
|
111 byte[] addr = new byte[4];
|
|
112 d_in.readFully(addr);
|
|
113
|
|
114 if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] != 0)
|
|
115 mode4a = true;
|
|
116 else {
|
|
117 ip = bytes2IP(addr);
|
|
118 host = ip.getHostName();
|
|
119 }
|
|
120
|
|
121 if (!clientMode) {
|
|
122 StringBuilder sb = new StringBuilder();
|
|
123 int b;
|
|
124
|
|
125 while ((b = in.read()) != 0)
|
|
126 sb.append((char) b);
|
|
127
|
|
128 user = sb.toString();
|
|
129
|
|
130 if (mode4a) {
|
|
131 sb.setLength(0);
|
|
132
|
|
133 while ((b = in.read()) != 0)
|
|
134 sb.append((char) b);
|
|
135
|
|
136 host = sb.toString();
|
|
137 }
|
|
138 }
|
|
139 }
|
|
140 @Override
|
|
141 public void write(OutputStream out) throws IOException {
|
|
142 if (msgBytes == null) {
|
|
143 Socks4Message msg = new Socks4Message(version, command, ip, port, user);
|
|
144 msgBytes = msg.msgBytes;
|
|
145 msgLength = msg.msgLength;
|
|
146 }
|
|
147
|
|
148 out.write(msgBytes);
|
|
149 }
|
|
150
|
|
151 //Class methods
|
|
152 static InetAddress bytes2IP(byte[] addr) {
|
|
153 String s = bytes2IPV4(addr, 0);
|
|
154
|
|
155 try {
|
|
156 return InetAddress.getByName(s);
|
|
157 }
|
|
158 catch (UnknownHostException uh_ex) {
|
|
159 return null;
|
|
160 }
|
|
161 }
|
|
162
|
|
163 //Constants
|
|
164
|
|
165 static final String[] replyMessage = {
|
|
166 "Request Granted",
|
|
167 "Request Rejected or Failed",
|
|
168 "Failed request, can't connect to Identd",
|
|
169 "Failed request, bad user name"
|
|
170 };
|
|
171
|
|
172 static final int SOCKS_VERSION = 4;
|
|
173
|
|
174 public final static int REQUEST_CONNECT = 1;
|
|
175 public final static int REQUEST_BIND = 2;
|
|
176
|
|
177 public final static int REPLY_OK = 90;
|
|
178 public final static int REPLY_REJECTED = 91;
|
|
179 public final static int REPLY_NO_CONNECT = 92;
|
|
180 public final static int REPLY_BAD_IDENTD = 93;
|
|
181
|
|
182 }
|