1 /*
2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
132 // Principal db. principal -> pass. A case-insensitive TreeMap is used
133 // so that even if the client provides a name with different case, the KDC
134 // can still locate the principal and give back correct salt.
135 private TreeMap<String,char[]> passwords = new TreeMap<>
136 (String.CASE_INSENSITIVE_ORDER);
137
138 // Realm name
139 private String realm;
140 // KDC
141 private String kdc;
142 // Service port number
143 private int port;
144 // The request/response job queue
145 private BlockingQueue<Job> q = new ArrayBlockingQueue<>(100);
146 // Options
147 private Map<Option,Object> options = new HashMap<>();
148 // Realm-specific krb5.conf settings
149 private List<String> conf = new ArrayList<>();
150
151 private Thread thread1, thread2, thread3;
152 DatagramSocket u1 = null;
153 ServerSocket t1 = null;
154
155 /**
156 * Option names, to be expanded forever.
157 */
158 public static enum Option {
159 /**
160 * Whether pre-authentication is required. Default Boolean.TRUE
161 */
162 PREAUTH_REQUIRED,
163 /**
164 * Only issue TGT in RC4
165 */
166 ONLY_RC4_TGT,
167 /**
168 * Use RC4 as the first in preauth
169 */
170 RC4_FIRST_PREAUTH,
171 /**
1211 try {
1212 port = 8000 + new java.util.Random().nextInt(10000);
1213 u1 = null;
1214 u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
1215 t1 = new ServerSocket(port);
1216 break;
1217 } catch (Exception e) {
1218 if (u1 != null) u1.close();
1219 }
1220 }
1221 }
1222 final DatagramSocket udp = u1;
1223 final ServerSocket tcp = t1;
1224 System.out.println("Start KDC on " + port);
1225
1226 this.port = port;
1227
1228 // The UDP consumer
1229 thread1 = new Thread() {
1230 public void run() {
1231 while (true) {
1232 try {
1233 byte[] inbuf = new byte[8192];
1234 DatagramPacket p = new DatagramPacket(inbuf, inbuf.length);
1235 udp.receive(p);
1236 System.out.println("-----------------------------------------------");
1237 System.out.println(">>>>> UDP packet received");
1238 q.put(new Job(processMessage(Arrays.copyOf(inbuf, p.getLength())), udp, p));
1239 } catch (Exception e) {
1240 e.printStackTrace();
1241 }
1242 }
1243 }
1244 };
1245 thread1.setDaemon(asDaemon);
1246 thread1.start();
1247
1248 // The TCP consumer
1249 thread2 = new Thread() {
1250 public void run() {
1251 while (true) {
1252 try {
1253 Socket socket = tcp.accept();
1254 System.out.println("-----------------------------------------------");
1255 System.out.println(">>>>> TCP connection established");
1256 DataInputStream in = new DataInputStream(socket.getInputStream());
1257 DataOutputStream out = new DataOutputStream(socket.getOutputStream());
1258 byte[] token = new byte[in.readInt()];
1259 in.readFully(token);
1260 q.put(new Job(processMessage(token), socket, out));
1261 } catch (Exception e) {
1262 e.printStackTrace();
1263 }
1264 }
1265 }
1266 };
1267 thread2.setDaemon(asDaemon);
1268 thread2.start();
1269
1270 // The dispatcher
1271 thread3 = new Thread() {
1272 public void run() {
1273 while (true) {
1274 try {
1275 q.take().send();
1276 } catch (Exception e) {
1277 }
1278 }
1279 }
1280 };
1281 thread3.setDaemon(true);
1282 thread3.start();
1283 }
1284
1285 public void terminate() {
1286 try {
1287 thread1.stop();
1288 thread2.stop();
1289 thread3.stop();
1290 u1.close();
1291 t1.close();
1292 } catch (Exception e) {
1293 // OK
1294 }
1295 }
1296 /**
1297 * Helper class to encapsulate a job in a KDC.
1298 */
1299 private static class Job {
1300 byte[] token; // The received request at creation time and
1301 // the response at send time
1302 Socket s; // The TCP socket from where the request comes
|
1 /*
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
132 // Principal db. principal -> pass. A case-insensitive TreeMap is used
133 // so that even if the client provides a name with different case, the KDC
134 // can still locate the principal and give back correct salt.
135 private TreeMap<String,char[]> passwords = new TreeMap<>
136 (String.CASE_INSENSITIVE_ORDER);
137
138 // Realm name
139 private String realm;
140 // KDC
141 private String kdc;
142 // Service port number
143 private int port;
144 // The request/response job queue
145 private BlockingQueue<Job> q = new ArrayBlockingQueue<>(100);
146 // Options
147 private Map<Option,Object> options = new HashMap<>();
148 // Realm-specific krb5.conf settings
149 private List<String> conf = new ArrayList<>();
150
151 private Thread thread1, thread2, thread3;
152 private volatile boolean udpConcumerReady = false;
153 private volatile boolean tcpConcumerReady = false;
154 private volatile boolean dispatcherReady = false;
155 DatagramSocket u1 = null;
156 ServerSocket t1 = null;
157
158 /**
159 * Option names, to be expanded forever.
160 */
161 public static enum Option {
162 /**
163 * Whether pre-authentication is required. Default Boolean.TRUE
164 */
165 PREAUTH_REQUIRED,
166 /**
167 * Only issue TGT in RC4
168 */
169 ONLY_RC4_TGT,
170 /**
171 * Use RC4 as the first in preauth
172 */
173 RC4_FIRST_PREAUTH,
174 /**
1214 try {
1215 port = 8000 + new java.util.Random().nextInt(10000);
1216 u1 = null;
1217 u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
1218 t1 = new ServerSocket(port);
1219 break;
1220 } catch (Exception e) {
1221 if (u1 != null) u1.close();
1222 }
1223 }
1224 }
1225 final DatagramSocket udp = u1;
1226 final ServerSocket tcp = t1;
1227 System.out.println("Start KDC on " + port);
1228
1229 this.port = port;
1230
1231 // The UDP consumer
1232 thread1 = new Thread() {
1233 public void run() {
1234 udpConcumerReady = true;
1235 while (true) {
1236 try {
1237 byte[] inbuf = new byte[8192];
1238 DatagramPacket p = new DatagramPacket(inbuf, inbuf.length);
1239 udp.receive(p);
1240 System.out.println("-----------------------------------------------");
1241 System.out.println(">>>>> UDP packet received");
1242 q.put(new Job(processMessage(Arrays.copyOf(inbuf, p.getLength())), udp, p));
1243 } catch (Exception e) {
1244 e.printStackTrace();
1245 }
1246 }
1247 }
1248 };
1249 thread1.setDaemon(asDaemon);
1250 thread1.start();
1251
1252 // The TCP consumer
1253 thread2 = new Thread() {
1254 public void run() {
1255 tcpConcumerReady = true;
1256 while (true) {
1257 try {
1258 Socket socket = tcp.accept();
1259 System.out.println("-----------------------------------------------");
1260 System.out.println(">>>>> TCP connection established");
1261 DataInputStream in = new DataInputStream(socket.getInputStream());
1262 DataOutputStream out = new DataOutputStream(socket.getOutputStream());
1263 byte[] token = new byte[in.readInt()];
1264 in.readFully(token);
1265 q.put(new Job(processMessage(token), socket, out));
1266 } catch (Exception e) {
1267 e.printStackTrace();
1268 }
1269 }
1270 }
1271 };
1272 thread2.setDaemon(asDaemon);
1273 thread2.start();
1274
1275 // The dispatcher
1276 thread3 = new Thread() {
1277 public void run() {
1278 dispatcherReady = true;
1279 while (true) {
1280 try {
1281 q.take().send();
1282 } catch (Exception e) {
1283 }
1284 }
1285 }
1286 };
1287 thread3.setDaemon(true);
1288 thread3.start();
1289 }
1290
1291 boolean isReady() {
1292 return udpConcumerReady && tcpConcumerReady && dispatcherReady;
1293 }
1294
1295 public void terminate() {
1296 try {
1297 thread1.stop();
1298 thread2.stop();
1299 thread3.stop();
1300 u1.close();
1301 t1.close();
1302 } catch (Exception e) {
1303 // OK
1304 }
1305 }
1306 /**
1307 * Helper class to encapsulate a job in a KDC.
1308 */
1309 private static class Job {
1310 byte[] token; // The received request at creation time and
1311 // the response at send time
1312 Socket s; // The TCP socket from where the request comes
|