1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.example.proxy;
21
22 import java.io.DataInputStream;
23 import java.io.DataOutputStream;
24 import java.io.IOException;
25 import java.net.ServerSocket;
26 import java.net.Socket;
27
28 import org.apache.mina.proxy.handlers.socks.SocksProxyConstants;
29 import org.apache.mina.proxy.utils.ByteUtilities;
30 import org.ietf.jgss.GSSContext;
31 import org.ietf.jgss.GSSCredential;
32 import org.ietf.jgss.GSSException;
33 import org.ietf.jgss.GSSManager;
34 import org.ietf.jgss.Oid;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class Socks5GSSAPITestServer {
54
55 private final static Logger logger = LoggerFactory
56 .getLogger(Socks5GSSAPITestServer.class);
57
58
59
60
61 protected final static String SERVICE_NAME = "host/myworkstation.local.network";
62
63
64
65
66
67 public final static byte[] SELECT_GSSAPI_AUTH_MSG = new byte[] {
68 SocksProxyConstants.SOCKS_VERSION_5,
69 SocksProxyConstants.GSSAPI_AUTH };
70
71
72
73
74
75
76
77
78 private static void doHandShake(int localPort) throws IOException,
79 GSSException {
80 ServerSocket ss = new ServerSocket(localPort);
81 GSSManager manager = GSSManager.getInstance();
82
83
84
85
86
87
88
89 GSSCredential serverCreds = manager.createCredential(manager
90 .createName(SERVICE_NAME, null),
91 GSSCredential.DEFAULT_LIFETIME, new Oid(
92 SocksProxyConstants.KERBEROS_V5_OID),
93 GSSCredential.ACCEPT_ONLY);
94
95 while (true) {
96 logger.debug("Waiting for incoming connection on port {} ...",
97 localPort);
98 GSSContext context = manager.createContext(serverCreds);
99 Socket socket = ss.accept();
100
101 try {
102 DataInputStream inStream = new DataInputStream(socket
103 .getInputStream());
104 DataOutputStream outStream = new DataOutputStream(socket
105 .getOutputStream());
106
107 logger.debug("Got connection from client @ {}", socket
108 .getInetAddress());
109
110
111 byte ver = (byte) inStream.read();
112 if (ver != 0x05) {
113 throw new IllegalStateException(
114 "Wrong socks version received - " + ver);
115 }
116 byte nbAuthMethods = (byte) inStream.read();
117 byte[] methods = new byte[nbAuthMethods];
118 inStream.readFully(methods);
119
120 boolean found = false;
121 for (byte b : methods) {
122 if (b == SocksProxyConstants.GSSAPI_AUTH) {
123 found = true;
124 break;
125 }
126 }
127
128 if (!found) {
129 throw new IllegalStateException(
130 "Client does not support GSSAPI authentication");
131 }
132
133
134 outStream.write(SELECT_GSSAPI_AUTH_MSG);
135 outStream.flush();
136
137
138 byte[] token = null;
139
140 while (!context.isEstablished()) {
141 byte authVersion = (byte) inStream.read();
142
143 if (authVersion != 0x01) {
144 throw new IllegalStateException(
145 "Wrong socks GSSAPI auth version received: "
146 + authVersion);
147 }
148
149 byte mtyp = (byte) inStream.read();
150 if (mtyp != 0x01) {
151 throw new IllegalArgumentException(
152 "Message type should be equal to 1.");
153 }
154
155 int len = inStream.readShort();
156 token = new byte[len];
157 inStream.readFully(token);
158 logger.debug(" Received Token[{}] = {}", len,
159 ByteUtilities.asHex(token));
160
161 token = context.acceptSecContext(token, 0, token.length);
162
163
164 if (token != null) {
165 logger.debug(" Sending Token[{}] = {}", token.length,
166 ByteUtilities.asHex(token));
167 outStream.writeByte(authVersion);
168 outStream.writeByte(mtyp);
169 outStream.writeShort(token.length);
170 outStream.write(token);
171 outStream.flush();
172 }
173 }
174
175 logger.debug("Context Established !");
176 logger.debug("Client is {}", context.getSrcName());
177 logger.debug("Server is {}", context.getTargName());
178
179
180
181
182
183
184
185 if (context.getMutualAuthState()) {
186 logger.debug("Mutual authentication took place !");
187 }
188
189
190
191 Thread.sleep(500);
192 } catch (Exception ex) {
193
194 } finally {
195 context.dispose();
196 socket.close();
197 }
198 }
199 }
200
201
202
203
204 public static void main(String[] args) throws Exception {
205
206 if (args.length != 1) {
207 System.err
208 .println("Usage: java <options> Socks5GSSAPITestServer <localPort>");
209 System.exit(-1);
210 }
211
212 doHandShake(Integer.parseInt(args[0]));
213 System.exit(0);
214 }
215 }