KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sslexplorer > boot > SSLTransportJCE


1 package com.sslexplorer.boot;
2
3 import java.io.EOFException JavaDoc;
4 import java.io.FileNotFoundException JavaDoc;
5 import java.io.IOException JavaDoc;
6 import java.io.InputStream JavaDoc;
7 import java.io.OutputStream JavaDoc;
8 import java.nio.ByteBuffer JavaDoc;
9
10 import javax.net.ssl.SSLContext;
11 import javax.net.ssl.SSLEngine;
12 import javax.net.ssl.SSLEngineResult;
13 import javax.net.ssl.SSLSession;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17
18 import com.maverick.ssl.SSLException;
19 import com.maverick.ssl.SSLTransport;
20
21 /**
22  */

23 public class SSLTransportJCE implements SSLTransport {
24
25     private static SSLContext sslContext;
26     private SSLSession session;
27     private SSLEngine engine;
28     private SSLEngineResult.HandshakeStatus hsStatus;
29     private boolean initialHandshake;
30
31     SSLEngineResult res;
32     static Log log = LogFactory.getLog(SSLTransportJCE.class);
33     
34     private InputStream JavaDoc rawIn;
35     private OutputStream JavaDoc rawOut;
36     
37     byte[] buffer;
38
39     ByteBuffer JavaDoc in_outputData;
40     ByteBuffer JavaDoc in_inputData;
41     ByteBuffer JavaDoc out_outputData;
42     
43     InputStream JavaDoc sslIn = new SSLInputStream();
44     OutputStream JavaDoc sslOut = new SSLOutputStream();
45     
46
47     public InputStream JavaDoc getInputStream() {
48         return sslIn;
49     }
50     
51     public OutputStream JavaDoc getOutputStream() {
52         return sslOut;
53     }
54     
55     public void initialize(InputStream JavaDoc in, OutputStream JavaDoc out) throws IOException JavaDoc {
56         this.rawIn = in;
57         this.rawOut = out;
58         
59 // Initialize SSL
60
try {
61             // Create an SSLEngine to use
62
engine = getSSLContext().createSSLEngine();
63
64             // Duh! we're the server
65
engine.setUseClientMode(true);
66
67             // Get the session and begin the handshake
68
session = engine.getSession();
69             engine.beginHandshake();
70             hsStatus = engine.getHandshakeStatus();
71             initialHandshake = true;
72
73             // This is a dummy byte buffer which is used during initial
74
// handshake negotiation
75
buffer = new byte[session.getPacketBufferSize()];
76
77             performInitialHandshake();
78
79             in_outputData = ByteBuffer.allocateDirect(session.getPacketBufferSize());
80             in_inputData = ByteBuffer.allocateDirect(session.getPacketBufferSize());
81             out_outputData = ByteBuffer.allocateDirect(session.getPacketBufferSize());
82             in_outputData.flip(); // Force an empty buffer state
83
} catch(Exception JavaDoc ex) {
84             throw new IOException JavaDoc(ex.getMessage());
85         }
86     }
87     
88     private void performInitialHandshake() throws IOException JavaDoc {
89         
90             /**
91              * Perform the initial handshake operation
92              */

93             ByteBuffer JavaDoc dummy = ByteBuffer.allocate(0);
94             ByteBuffer JavaDoc outputBuffer = ByteBuffer.allocateDirect(session.getPacketBufferSize());
95             ByteBuffer JavaDoc inputBuffer = ByteBuffer.allocateDirect(session.getPacketBufferSize());
96         
97             while(initialHandshake) {
98     
99             switch (hsStatus) {
100             case FINISHED:
101                 /**
102                  * We have completed the handshake so lets start doing the real stuff
103                  */

104                 
105                 if(log.isDebugEnabled())
106                     log.debug("SSL Handshake finished");
107                 initialHandshake = false;
108                 return;
109     
110             case NEED_TASK:
111     
112                 /**
113                  * The SSL engine needs to perform a task... do it!
114                  */

115                 if(log.isDebugEnabled())
116                     log.debug("Performing SSLEngine task");
117     
118                 // Execute the tasks
119
Runnable JavaDoc task;
120                 while ((task = engine.getDelegatedTask()) != null) {
121                     task.run();
122                 }
123                 hsStatus = engine.getHandshakeStatus();
124                 break;
125     
126             case NEED_UNWRAP:
127     
128                 /**
129                  * SSL engine wants more data to make sure we're reading from
130                  * the socket
131                  */

132                 if(log.isDebugEnabled())
133                     log.debug("Reading SSL data from raw InputStream");
134     
135                 inputBuffer.flip();
136                 
137                 if(!inputBuffer.hasRemaining()) {
138                     
139                     inputBuffer.compact();
140                     int read = rawIn.read(buffer);
141     
142                     if(read==-1)
143                         throw new EOFException JavaDoc("Unexpected EOF whilst waiting for SSL unwrap");
144                 
145                     inputBuffer.put(buffer, 0, read);
146                     inputBuffer.flip();
147                 }
148     
149                 res = engine.unwrap(inputBuffer, outputBuffer);
150     
151                 inputBuffer.compact();
152
153                 if(res.getStatus()!=SSLEngineResult.Status.OK) {
154                     throw new IOException JavaDoc(res.getStatus().toString());
155                 }
156                 
157                 hsStatus = res.getHandshakeStatus();
158                 
159                 sendOutput(outputBuffer);
160                 break;
161     
162             case NEED_WRAP:
163     
164                 /**
165                  * SSL engine wants to write data to the socket so make sure
166                  * we can write to it
167                  */

168                 
169                 if(log.isDebugEnabled())
170                     log.debug("Writing SSL data to raw OutputStream");
171
172                 res = engine.wrap(dummy, outputBuffer);
173                 
174                 if(res.getStatus()!=SSLEngineResult.Status.OK) {
175                     throw new IOException JavaDoc(res.getStatus().toString());
176                 }
177                 
178                 hsStatus = res.getHandshakeStatus();
179
180                 sendOutput(outputBuffer);
181                 
182                 break;
183     
184             case NOT_HANDSHAKING:
185                 /**
186                  * This state should never be caught here
187                  */

188                 log.error("doHandshake has caught a NOT_HANDSHAKING state.. This is impossible!");
189             }
190         }
191     }
192     
193     private void sendOutput(ByteBuffer JavaDoc outputBuffer) throws IOException JavaDoc {
194         outputBuffer.flip();
195         
196         int remaining = outputBuffer.remaining();
197         while(remaining > 0) {
198             outputBuffer.get(buffer, 0, remaining);
199             rawOut.write(buffer, 0, remaining);
200             remaining = outputBuffer.remaining();
201         }
202         
203         outputBuffer.compact();
204     }
205     
206     /**
207      * Get the SSL context. If SSL isn't initialized when this is called we
208      * initialize it.
209      * @return SSLContext
210      * @throws IOException
211      */

212     private synchronized static SSLContext getSSLContext() throws IOException JavaDoc {
213         if (sslContext != null) {
214             return sslContext;
215         }
216         initializeSSL();
217         return sslContext;
218     }
219
220     /**
221      * Initialize SSL. If at all possible this should be called before any
222      * connection attempts are made.
223      * @throws FileNotFoundException
224      * @throws IOException
225      */

226     public static void initializeSSL() throws FileNotFoundException JavaDoc, IOException JavaDoc {
227         try {
228             sslContext = SSLContext.getInstance("TLS");
229             sslContext.init(SSLKeyManager.getKeyManagerArray(), SSLTrustManager.getTrustManagerArray(), null);
230         } catch (Exception JavaDoc ex) {
231             throw new IOException JavaDoc("SSL initialization failed: " + ex.getMessage());
232         }
233     }
234     
235     /**
236      * Initializes the SSLContext with the value supplied.
237      * @param context
238      */

239     public synchronized static void setSSLContext(SSLContext context) {
240         sslContext = context;
241     }
242     
243     class SSLInputStream extends InputStream JavaDoc {
244         
245         SSLInputStream() {
246             
247         }
248         
249         public int read() throws IOException JavaDoc {
250             byte[] b = new byte[1];
251             if(readData(b,0,1)==1)
252                 return (int) b[0];
253             else
254                 return -1;
255         }
256         
257         public int read(byte[] buf, int off, int len) throws IOException JavaDoc {
258             return readData(buf, off, len);
259         }
260         
261         /**
262          * @param buf
263          * @param off
264          * @param len
265          * @return int
266          * @throws IOException
267          */

268         public int readData(byte[] buf, int off, int len) throws IOException JavaDoc {
269             
270             try {
271                 while(true) {
272
273                     if(in_outputData.hasRemaining()) {
274                         int actualLen = Math.min(len, in_outputData.remaining());
275                         in_outputData.get(buf, off, actualLen);
276                         return actualLen;
277                     }
278                     
279                     int read = -1;
280                     
281                     do {
282                         
283                         in_inputData.flip();
284                         
285                         if(!in_inputData.hasRemaining() || res.getStatus()==SSLEngineResult.Status.BUFFER_UNDERFLOW) {
286                             
287                             in_inputData.compact();
288                             read = rawIn.read(buffer, 0, Math.min(in_inputData.remaining(), buffer.length));
289                             
290                             if(read==-1)
291                                 return -1;
292                             
293                             if(read==0)
294                                 return 0;
295
296                             in_inputData.put(buffer,0,read);
297                             in_inputData.flip();
298                         }
299                         
300                         in_outputData.compact();
301                         res = engine.unwrap(in_inputData, in_outputData);
302                         in_outputData.flip();
303                         in_inputData.compact();
304                     
305                     } while(res.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW);
306                     
307                 }
308             } catch (IOException JavaDoc e) {
309                 if(log.isDebugEnabled())
310                     log.error(e);
311                 throw e;
312             }
313             
314         }
315     }
316     
317     
318     class SSLOutputStream extends OutputStream JavaDoc {
319         
320         public void write(int b) throws IOException JavaDoc {
321             writeData(new byte[] { (byte)b }, 0, 1);
322         }
323         
324         public void write(byte[] buf, int off, int len) throws IOException JavaDoc {
325             writeData(buf, off, len);
326         }
327         
328         void writeData(byte[] buf, int off, int len) throws IOException JavaDoc {
329             
330             ByteBuffer JavaDoc source = ByteBuffer.wrap(buf, off, len);
331             
332             while(source.remaining() > 0) {
333                 res = engine.wrap(source, out_outputData);
334                 
335                 out_outputData.flip();
336                 
337                 int remaining = out_outputData.remaining();
338                 while(remaining > 0) {
339                     out_outputData.get(buffer, 0, remaining);
340                     rawOut.write(buffer, 0, remaining);
341                     remaining = out_outputData.remaining();
342                 }
343                 out_outputData.compact();
344             }
345         }
346     }
347     
348     public void close() throws SSLException {
349     
350         try {
351
352             if(!engine.isOutboundDone())
353                 engine.closeOutbound();
354             
355             if(engine.isInboundDone())
356                 engine.closeInbound();
357             
358         } catch (Exception JavaDoc e) {
359         } finally {
360             Util.closeStream(rawIn);
361             Util.closeStream(rawOut);
362         }
363         
364     }
365 }
366
Popular Tags