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