Source Code Cross Referenced for SslHandler.java in  » Net » mina-2.0.0-M1 » org » apache » mina » filter » ssl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » mina 2.0.0 M1 » org.apache.mina.filter.ssl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Licensed to the Apache Software Foundation (ASF) under one
003:         *  or more contributor license agreements.  See the NOTICE file
004:         *  distributed with this work for additional information
005:         *  regarding copyright ownership.  The ASF licenses this file
006:         *  to you under the Apache License, Version 2.0 (the
007:         *  "License"); you may not use this file except in compliance
008:         *  with the License.  You may obtain a copy of the License at
009:         *
010:         *    http://www.apache.org/licenses/LICENSE-2.0
011:         *
012:         *  Unless required by applicable law or agreed to in writing,
013:         *  software distributed under the License is distributed on an
014:         *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015:         *  KIND, either express or implied.  See the License for the
016:         *  specific language governing permissions and limitations
017:         *  under the License.
018:         *
019:         */
020:        package org.apache.mina.filter.ssl;
021:
022:        import java.net.InetSocketAddress;
023:        import java.nio.ByteBuffer;
024:        import java.util.Queue;
025:        import java.util.concurrent.ConcurrentLinkedQueue;
026:
027:        import javax.net.ssl.SSLContext;
028:        import javax.net.ssl.SSLEngine;
029:        import javax.net.ssl.SSLEngineResult;
030:        import javax.net.ssl.SSLException;
031:        import javax.net.ssl.SSLHandshakeException;
032:
033:        import org.apache.mina.common.DefaultWriteFuture;
034:        import org.apache.mina.common.DefaultWriteRequest;
035:        import org.apache.mina.common.IoBuffer;
036:        import org.apache.mina.common.IoEventType;
037:        import org.apache.mina.common.IoFilterEvent;
038:        import org.apache.mina.common.IoSession;
039:        import org.apache.mina.common.WriteFuture;
040:        import org.apache.mina.common.WriteRequest;
041:        import org.apache.mina.common.IoFilter.NextFilter;
042:        import org.apache.mina.util.CircularQueue;
043:        import org.slf4j.Logger;
044:        import org.slf4j.LoggerFactory;
045:
046:        /**
047:         * A helper class using the SSLEngine API to decrypt/encrypt data.
048:         * <p/>
049:         * Each connection has a SSLEngine that is used through the lifetime of the connection.
050:         * We allocate buffers for use as the outbound and inbound network buffers.
051:         * These buffers handle all of the intermediary data for the SSL connection. To make things easy,
052:         * we'll require outNetBuffer be completely flushed before trying to wrap any more data.
053:         *
054:         * @author The Apache MINA Project (dev@mina.apache.org)
055:         * @version $Rev: 616100 $, $Date: 2008-01-28 15:58:32 -0700 (Mon, 28 Jan 2008) $
056:         */
057:        class SslHandler {
058:
059:            private final Logger logger = LoggerFactory.getLogger(getClass());
060:            private final SslFilter parent;
061:            private final SSLContext ctx;
062:            private final IoSession session;
063:            private final Queue<IoFilterEvent> preHandshakeEventQueue = new CircularQueue<IoFilterEvent>();
064:            private final Queue<IoFilterEvent> filterWriteEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();
065:            private final Queue<IoFilterEvent> messageReceivedEventQueue = new ConcurrentLinkedQueue<IoFilterEvent>();
066:            private SSLEngine sslEngine;
067:
068:            /**
069:             * Encrypted data from the net
070:             */
071:            private IoBuffer inNetBuffer;
072:
073:            /**
074:             * Encrypted data to be written to the net
075:             */
076:            private IoBuffer outNetBuffer;
077:
078:            /**
079:             * Applicaton cleartext data to be read by application
080:             */
081:            private IoBuffer appBuffer;
082:
083:            /**
084:             * Empty buffer used during initial handshake and close operations
085:             */
086:            private final IoBuffer emptyBuffer = IoBuffer.allocate(0);
087:
088:            private SSLEngineResult.HandshakeStatus handshakeStatus;
089:            private boolean initialHandshakeComplete;
090:            private boolean handshakeComplete;
091:            private boolean writingEncryptedData;
092:
093:            /**
094:             * Constuctor.
095:             *
096:             * @param sslc
097:             * @throws SSLException
098:             */
099:            public SslHandler(SslFilter parent, SSLContext sslc,
100:                    IoSession session) throws SSLException {
101:                this .parent = parent;
102:                this .session = session;
103:                this .ctx = sslc;
104:                init();
105:            }
106:
107:            public void init() throws SSLException {
108:                if (sslEngine != null) {
109:                    return;
110:                }
111:
112:                InetSocketAddress peer = (InetSocketAddress) session
113:                        .getAttribute(SslFilter.PEER_ADDRESS);
114:                if (peer == null) {
115:                    sslEngine = ctx.createSSLEngine();
116:                } else {
117:                    sslEngine = ctx.createSSLEngine(peer.getHostName(), peer
118:                            .getPort());
119:                }
120:                sslEngine.setUseClientMode(parent.isUseClientMode());
121:
122:                if (parent.isWantClientAuth()) {
123:                    sslEngine.setWantClientAuth(true);
124:                }
125:
126:                if (parent.isNeedClientAuth()) {
127:                    sslEngine.setNeedClientAuth(true);
128:                }
129:
130:                if (parent.getEnabledCipherSuites() != null) {
131:                    sslEngine.setEnabledCipherSuites(parent
132:                            .getEnabledCipherSuites());
133:                }
134:
135:                if (parent.getEnabledProtocols() != null) {
136:                    sslEngine.setEnabledProtocols(parent.getEnabledProtocols());
137:                }
138:
139:                sslEngine.beginHandshake();
140:                handshakeStatus = sslEngine.getHandshakeStatus();
141:
142:                handshakeComplete = false;
143:                initialHandshakeComplete = false;
144:                writingEncryptedData = false;
145:            }
146:
147:            /**
148:             * Release allocated buffers.
149:             */
150:            public void destroy() {
151:                if (sslEngine == null) {
152:                    return;
153:                }
154:
155:                // Close inbound and flush all remaining data if available.
156:                try {
157:                    sslEngine.closeInbound();
158:                } catch (SSLException e) {
159:                    logger
160:                            .debug(
161:                                    "Unexpected exception from SSLEngine.closeInbound().",
162:                                    e);
163:                }
164:
165:                if (outNetBuffer != null) {
166:                    outNetBuffer.capacity(sslEngine.getSession()
167:                            .getPacketBufferSize());
168:                } else {
169:                    createOutNetBuffer(0);
170:                }
171:                try {
172:                    do {
173:                        outNetBuffer.clear();
174:                    } while (sslEngine.wrap(emptyBuffer.buf(),
175:                            outNetBuffer.buf()).bytesProduced() > 0);
176:                } catch (SSLException e) {
177:                    // Ignore.
178:                } finally {
179:                    destroyOutNetBuffer();
180:                }
181:
182:                sslEngine.closeOutbound();
183:                sslEngine = null;
184:
185:                preHandshakeEventQueue.clear();
186:            }
187:
188:            private void destroyOutNetBuffer() {
189:                outNetBuffer.free();
190:                outNetBuffer = null;
191:            }
192:
193:            public SslFilter getParent() {
194:                return parent;
195:            }
196:
197:            public IoSession getSession() {
198:                return session;
199:            }
200:
201:            /**
202:             * Check we are writing encrypted data.
203:             */
204:            public boolean isWritingEncryptedData() {
205:                return writingEncryptedData;
206:            }
207:
208:            /**
209:             * Check if handshake is completed.
210:             */
211:            public boolean isHandshakeComplete() {
212:                return handshakeComplete;
213:            }
214:
215:            public boolean isInboundDone() {
216:                return sslEngine == null || sslEngine.isInboundDone();
217:            }
218:
219:            public boolean isOutboundDone() {
220:                return sslEngine == null || sslEngine.isOutboundDone();
221:            }
222:
223:            /**
224:             * Check if there is any need to complete handshake.
225:             */
226:            public boolean needToCompleteHandshake() {
227:                return handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP
228:                        && !isInboundDone();
229:            }
230:
231:            public void schedulePreHandshakeWriteRequest(NextFilter nextFilter,
232:                    WriteRequest writeRequest) {
233:                preHandshakeEventQueue.add(new IoFilterEvent(nextFilter,
234:                        IoEventType.WRITE, session, writeRequest));
235:            }
236:
237:            public void flushPreHandshakeEvents() throws SSLException {
238:                IoFilterEvent scheduledWrite;
239:
240:                while ((scheduledWrite = preHandshakeEventQueue.poll()) != null) {
241:                    parent.filterWrite(scheduledWrite.getNextFilter(), session,
242:                            (WriteRequest) scheduledWrite.getParameter());
243:                }
244:            }
245:
246:            public void scheduleFilterWrite(NextFilter nextFilter,
247:                    WriteRequest writeRequest) {
248:                filterWriteEventQueue.add(new IoFilterEvent(nextFilter,
249:                        IoEventType.WRITE, session, writeRequest));
250:            }
251:
252:            public void scheduleMessageReceived(NextFilter nextFilter,
253:                    Object message) {
254:                messageReceivedEventQueue.add(new IoFilterEvent(nextFilter,
255:                        IoEventType.MESSAGE_RECEIVED, session, message));
256:            }
257:
258:            public void flushScheduledEvents() {
259:                // Fire events only when no lock is hold for this handler.
260:                if (Thread.holdsLock(this )) {
261:                    return;
262:                }
263:
264:                IoFilterEvent e;
265:
266:                // We need synchronization here inevitably because filterWrite can be
267:                // called simultaneously and cause 'bad record MAC' integrity error.
268:                synchronized (this ) {
269:                    while ((e = filterWriteEventQueue.poll()) != null) {
270:                        e.getNextFilter().filterWrite(session,
271:                                (WriteRequest) e.getParameter());
272:                    }
273:                }
274:
275:                while ((e = messageReceivedEventQueue.poll()) != null) {
276:                    e.getNextFilter()
277:                            .messageReceived(session, e.getParameter());
278:                }
279:            }
280:
281:            /**
282:             * Call when data read from net. Will perform inial hanshake or decrypt provided
283:             * Buffer.
284:             * Decrytpted data reurned by getAppBuffer(), if any.
285:             *
286:             * @param buf        buffer to decrypt
287:             * @param nextFilter Next filter in chain
288:             * @throws SSLException on errors
289:             */
290:            public void messageReceived(NextFilter nextFilter, ByteBuffer buf)
291:                    throws SSLException {
292:                // append buf to inNetBuffer
293:                if (inNetBuffer == null) {
294:                    inNetBuffer = IoBuffer.allocate(buf.remaining())
295:                            .setAutoExpand(true);
296:                }
297:
298:                inNetBuffer.put(buf);
299:                if (!handshakeComplete) {
300:                    handshake(nextFilter);
301:                } else {
302:                    decrypt(nextFilter);
303:                }
304:
305:                if (isInboundDone()) {
306:                    // Rewind the MINA buffer if not all data is processed and inbound is finished.
307:                    int inNetBufferPosition = inNetBuffer == null ? 0
308:                            : inNetBuffer.position();
309:                    buf.position(buf.position() - inNetBufferPosition);
310:                    inNetBuffer = null;
311:                }
312:            }
313:
314:            /**
315:             * Get decrypted application data.
316:             *
317:             * @return buffer with data
318:             */
319:            public IoBuffer fetchAppBuffer() {
320:                IoBuffer appBuffer = this .appBuffer.flip();
321:                this .appBuffer = null;
322:                return appBuffer;
323:            }
324:
325:            /**
326:             * Get encrypted data to be sent.
327:             *
328:             * @return buffer with data
329:             */
330:            public IoBuffer fetchOutNetBuffer() {
331:                IoBuffer answer = outNetBuffer;
332:                if (answer == null) {
333:                    return emptyBuffer;
334:                }
335:
336:                outNetBuffer = null;
337:                return answer.shrink();
338:            }
339:
340:            /**
341:             * Encrypt provided buffer. Encytpted data reurned by getOutNetBuffer().
342:             *
343:             * @param src data to encrypt
344:             * @throws SSLException on errors
345:             */
346:            public void encrypt(ByteBuffer src) throws SSLException {
347:                if (!handshakeComplete) {
348:                    throw new IllegalStateException();
349:                }
350:
351:                if (!src.hasRemaining()) {
352:                    if (outNetBuffer == null) {
353:                        outNetBuffer = emptyBuffer;
354:                    }
355:                    return;
356:                }
357:
358:                createOutNetBuffer(src.remaining());
359:
360:                // Loop until there is no more data in src
361:                while (src.hasRemaining()) {
362:
363:                    SSLEngineResult result = sslEngine.wrap(src, outNetBuffer
364:                            .buf());
365:                    if (result.getStatus() == SSLEngineResult.Status.OK) {
366:                        if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
367:                            doTasks();
368:                        }
369:                    } else if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
370:                        outNetBuffer.capacity(outNetBuffer.capacity() << 1);
371:                        outNetBuffer.limit(outNetBuffer.capacity());
372:                    } else {
373:                        throw new SSLException(
374:                                "SSLEngine error during encrypt: "
375:                                        + result.getStatus() + " src: " + src
376:                                        + "outNetBuffer: " + outNetBuffer);
377:                    }
378:                }
379:
380:                outNetBuffer.flip();
381:            }
382:
383:            /**
384:             * Start SSL shutdown process.
385:             *
386:             * @return <tt>true</tt> if shutdown process is started.
387:             *         <tt>false</tt> if shutdown process is already finished.
388:             * @throws SSLException on errors
389:             */
390:            public boolean closeOutbound() throws SSLException {
391:                if (sslEngine == null || sslEngine.isOutboundDone()) {
392:                    return false;
393:                }
394:
395:                sslEngine.closeOutbound();
396:
397:                createOutNetBuffer(0);
398:                SSLEngineResult result;
399:                for (;;) {
400:                    result = sslEngine.wrap(emptyBuffer.buf(), outNetBuffer
401:                            .buf());
402:                    if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
403:                        outNetBuffer.capacity(outNetBuffer.capacity() << 1);
404:                        outNetBuffer.limit(outNetBuffer.capacity());
405:                    } else {
406:                        break;
407:                    }
408:                }
409:
410:                if (result.getStatus() != SSLEngineResult.Status.CLOSED) {
411:                    throw new SSLException("Improper close state: " + result);
412:                }
413:                outNetBuffer.flip();
414:                return true;
415:            }
416:
417:            /**
418:             * Decrypt in net buffer. Result is stored in app buffer.
419:             *
420:             * @throws SSLException
421:             */
422:            private void decrypt(NextFilter nextFilter) throws SSLException {
423:
424:                if (!handshakeComplete) {
425:                    throw new IllegalStateException();
426:                }
427:
428:                unwrap(nextFilter);
429:            }
430:
431:            /**
432:             * @param res
433:             * @throws SSLException
434:             */
435:            private void checkStatus(SSLEngineResult res) throws SSLException {
436:
437:                SSLEngineResult.Status status = res.getStatus();
438:
439:                /*
440:                 * The status may be:
441:                 * OK - Normal operation
442:                 * OVERFLOW - Should never happen since the application buffer is
443:                 *      sized to hold the maximum packet size.
444:                 * UNDERFLOW - Need to read more data from the socket. It's normal.
445:                 * CLOSED - The other peer closed the socket. Also normal.
446:                 */
447:                if (status != SSLEngineResult.Status.OK
448:                        && status != SSLEngineResult.Status.CLOSED
449:                        && status != SSLEngineResult.Status.BUFFER_UNDERFLOW) {
450:                    throw new SSLException("SSLEngine error during decrypt: "
451:                            + status + " inNetBuffer: " + inNetBuffer
452:                            + "appBuffer: " + appBuffer);
453:                }
454:            }
455:
456:            /**
457:             * Perform any handshaking processing.
458:             */
459:            public void handshake(NextFilter nextFilter) throws SSLException {
460:                for (;;) {
461:                    if (handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED) {
462:                        session.setAttribute(SslFilter.SSL_SESSION, sslEngine
463:                                .getSession());
464:                        handshakeComplete = true;
465:                        if (!initialHandshakeComplete
466:                                && session
467:                                        .containsAttribute(SslFilter.USE_NOTIFICATION)) {
468:                            // SESSION_SECURED is fired only when it's the first handshake.
469:                            // (i.e. renegotiation shouldn't trigger SESSION_SECURED.)
470:                            initialHandshakeComplete = true;
471:                            scheduleMessageReceived(nextFilter,
472:                                    SslFilter.SESSION_SECURED);
473:                        }
474:                        break;
475:                    } else if (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) {
476:                        handshakeStatus = doTasks();
477:                    } else if (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
478:                        // we need more data read
479:                        SSLEngineResult.Status status = unwrapHandshake(nextFilter);
480:                        if (status == SSLEngineResult.Status.BUFFER_UNDERFLOW
481:                                || isInboundDone()) {
482:                            // We need more data or the session is closed
483:                            break;
484:                        }
485:                    } else if (handshakeStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
486:                        // First make sure that the out buffer is completely empty. Since we
487:                        // cannot call wrap with data left on the buffer
488:                        if (outNetBuffer != null && outNetBuffer.hasRemaining()) {
489:                            break;
490:                        }
491:
492:                        SSLEngineResult result;
493:                        createOutNetBuffer(0);
494:                        for (;;) {
495:                            result = sslEngine.wrap(emptyBuffer.buf(),
496:                                    outNetBuffer.buf());
497:                            if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
498:                                outNetBuffer
499:                                        .capacity(outNetBuffer.capacity() << 1);
500:                                outNetBuffer.limit(outNetBuffer.capacity());
501:                            } else {
502:                                break;
503:                            }
504:                        }
505:
506:                        outNetBuffer.flip();
507:                        handshakeStatus = result.getHandshakeStatus();
508:                        writeNetBuffer(nextFilter);
509:                    } else {
510:                        throw new IllegalStateException(
511:                                "Invalid Handshaking State" + handshakeStatus);
512:                    }
513:                }
514:            }
515:
516:            private void createOutNetBuffer(int expectedRemaining) {
517:                // SSLEngine requires us to allocate unnecessarily big buffer
518:                // even for small data.  *Shrug*
519:                int capacity = Math.max(expectedRemaining, sslEngine
520:                        .getSession().getPacketBufferSize());
521:
522:                if (outNetBuffer != null) {
523:                    outNetBuffer.capacity(capacity);
524:                } else {
525:                    outNetBuffer = IoBuffer.allocate(capacity).minimumCapacity(
526:                            0);
527:                }
528:            }
529:
530:            public WriteFuture writeNetBuffer(NextFilter nextFilter)
531:                    throws SSLException {
532:                // Check if any net data needed to be writen
533:                if (outNetBuffer == null || !outNetBuffer.hasRemaining()) {
534:                    // no; bail out
535:                    return null;
536:                }
537:
538:                // set flag that we are writing encrypted data
539:                // (used in SSLFilter.filterWrite())
540:                writingEncryptedData = true;
541:
542:                // write net data
543:                WriteFuture writeFuture = null;
544:
545:                try {
546:                    IoBuffer writeBuffer = fetchOutNetBuffer();
547:                    writeFuture = new DefaultWriteFuture(session);
548:                    parent.filterWrite(nextFilter, session,
549:                            new DefaultWriteRequest(writeBuffer, writeFuture));
550:
551:                    // loop while more writes required to complete handshake
552:                    while (needToCompleteHandshake()) {
553:                        try {
554:                            handshake(nextFilter);
555:                        } catch (SSLException ssle) {
556:                            SSLException newSsle = new SSLHandshakeException(
557:                                    "SSL handshake failed.");
558:                            newSsle.initCause(ssle);
559:                            throw newSsle;
560:                        }
561:
562:                        IoBuffer outNetBuffer = fetchOutNetBuffer();
563:                        if (outNetBuffer != null && outNetBuffer.hasRemaining()) {
564:                            writeFuture = new DefaultWriteFuture(session);
565:                            parent.filterWrite(nextFilter, session,
566:                                    new DefaultWriteRequest(outNetBuffer,
567:                                            writeFuture));
568:                        }
569:                    }
570:                } finally {
571:                    writingEncryptedData = false;
572:                }
573:
574:                return writeFuture;
575:            }
576:
577:            private void unwrap(NextFilter nextFilter) throws SSLException {
578:                // Prepare the net data for reading.
579:                if (inNetBuffer != null) {
580:                    inNetBuffer.flip();
581:                }
582:
583:                if (inNetBuffer == null || !inNetBuffer.hasRemaining()) {
584:                    return;
585:                }
586:
587:                SSLEngineResult res = unwrap0();
588:
589:                // prepare to be written again
590:                if (inNetBuffer.hasRemaining()) {
591:                    inNetBuffer.compact();
592:                } else {
593:                    inNetBuffer = null;
594:                }
595:
596:                checkStatus(res);
597:
598:                renegotiateIfNeeded(nextFilter, res);
599:            }
600:
601:            private SSLEngineResult.Status unwrapHandshake(NextFilter nextFilter)
602:                    throws SSLException {
603:                // Prepare the net data for reading.
604:                if (inNetBuffer != null) {
605:                    inNetBuffer.flip();
606:                }
607:
608:                if (inNetBuffer == null || !inNetBuffer.hasRemaining()) {
609:                    // Need more data.
610:                    return SSLEngineResult.Status.BUFFER_UNDERFLOW;
611:                }
612:
613:                SSLEngineResult res = unwrap0();
614:                handshakeStatus = res.getHandshakeStatus();
615:
616:                checkStatus(res);
617:
618:                // If handshake finished, no data was produced, and the status is still ok,
619:                // try to unwrap more
620:                if (handshakeStatus == SSLEngineResult.HandshakeStatus.FINISHED
621:                        && res.getStatus() == SSLEngineResult.Status.OK
622:                        && inNetBuffer.hasRemaining()) {
623:                    res = unwrap0();
624:
625:                    // prepare to be written again
626:                    if (inNetBuffer.hasRemaining()) {
627:                        inNetBuffer.compact();
628:                    } else {
629:                        inNetBuffer = null;
630:                    }
631:
632:                    renegotiateIfNeeded(nextFilter, res);
633:                } else {
634:                    // prepare to be written again
635:                    if (inNetBuffer.hasRemaining()) {
636:                        inNetBuffer.compact();
637:                    } else {
638:                        inNetBuffer = null;
639:                    }
640:                }
641:
642:                return res.getStatus();
643:            }
644:
645:            private void renegotiateIfNeeded(NextFilter nextFilter,
646:                    SSLEngineResult res) throws SSLException {
647:                if (res.getStatus() != SSLEngineResult.Status.CLOSED
648:                        && res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW
649:                        && res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
650:                    // Renegotiation required.
651:                    handshakeComplete = false;
652:                    handshakeStatus = res.getHandshakeStatus();
653:                    handshake(nextFilter);
654:                }
655:            }
656:
657:            private SSLEngineResult unwrap0() throws SSLException {
658:                if (appBuffer == null) {
659:                    appBuffer = IoBuffer.allocate(inNetBuffer.remaining());
660:                } else {
661:                    appBuffer.expand(inNetBuffer.remaining());
662:                }
663:
664:                SSLEngineResult res;
665:                do {
666:                    res = sslEngine.unwrap(inNetBuffer.buf(), appBuffer.buf());
667:                    if (res.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
668:                        appBuffer.capacity(appBuffer.capacity() << 1);
669:                        appBuffer.limit(appBuffer.capacity());
670:                        continue;
671:                    }
672:                } while ((res.getStatus() == SSLEngineResult.Status.OK || res
673:                        .getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW)
674:                        && (handshakeComplete
675:                                && res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING || res
676:                                .getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP));
677:
678:                return res;
679:            }
680:
681:            /**
682:             * Do all the outstanding handshake tasks in the current Thread.
683:             */
684:            private SSLEngineResult.HandshakeStatus doTasks() {
685:                /*
686:                 * We could run this in a separate thread, but I don't see the need
687:                 * for this when used from SSLFilter. Use thread filters in MINA instead?
688:                 */
689:                Runnable runnable;
690:                while ((runnable = sslEngine.getDelegatedTask()) != null) {
691:                    runnable.run();
692:                }
693:                return sslEngine.getHandshakeStatus();
694:            }
695:
696:            /**
697:             * Creates a new MINA buffer that is a deep copy of the remaining bytes
698:             * in the given buffer (between index buf.position() and buf.limit())
699:             *
700:             * @param src the buffer to copy
701:             * @return the new buffer, ready to read from
702:             */
703:            public static IoBuffer copy(ByteBuffer src) {
704:                IoBuffer copy = IoBuffer.allocate(src.remaining());
705:                copy.put(src);
706:                copy.flip();
707:                return copy;
708:            }
709:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.