Source Code Cross Referenced for SslSocketConnector.java in  » Sevlet-Container » jetty-modules » org » mortbay » jetty » security » 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 » Sevlet Container » jetty modules » org.mortbay.jetty.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // ========================================================================
002:        // Copyright 2000-2005 Mort Bay Consulting Pty. Ltd.
003:        // ------------------------------------------------------------------------
004:        // Licensed under the Apache License, Version 2.0 (the "License");
005:        // you may not use this file except in compliance with the License.
006:        // You may obtain a copy of the License at 
007:        // http://www.apache.org/licenses/LICENSE-2.0
008:        // Unless required by applicable law or agreed to in writing, software
009:        // distributed under the License is distributed on an "AS IS" BASIS,
010:        // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011:        // See the License for the specific language governing permissions and
012:        // limitations under the License.
013:        // ========================================================================
014:
015:        package org.mortbay.jetty.security;
016:
017:        import java.io.ByteArrayInputStream;
018:        import java.io.IOException;
019:        import java.net.InetAddress;
020:        import java.net.ServerSocket;
021:        import java.net.Socket;
022:        import java.net.SocketAddress;
023:        import java.security.KeyStore;
024:        import java.security.SecureRandom;
025:        import java.security.Security;
026:        import java.security.cert.X509Certificate;
027:        import java.util.ArrayList;
028:        import java.util.Arrays;
029:        import java.util.Iterator;
030:        import java.util.List;
031:
032:        import javax.net.ssl.KeyManager;
033:        import javax.net.ssl.KeyManagerFactory;
034:        import javax.net.ssl.SSLContext;
035:        import javax.net.ssl.SSLException;
036:        import javax.net.ssl.SSLPeerUnverifiedException;
037:        import javax.net.ssl.SSLServerSocket;
038:        import javax.net.ssl.SSLServerSocketFactory;
039:        import javax.net.ssl.SSLSession;
040:        import javax.net.ssl.SSLSocket;
041:        import javax.net.ssl.TrustManager;
042:        import javax.net.ssl.TrustManagerFactory;
043:
044:        import org.mortbay.io.EndPoint;
045:        import org.mortbay.io.bio.SocketEndPoint;
046:        import org.mortbay.jetty.HttpSchemes;
047:        import org.mortbay.jetty.Request;
048:        import org.mortbay.jetty.bio.SocketConnector;
049:        import org.mortbay.log.Log;
050:        import org.mortbay.resource.Resource;
051:
052:        /* ------------------------------------------------------------ */
053:        /**
054:         * JSSE Socket Listener.
055:         * 
056:         * This specialization of HttpListener is an abstract listener that can be used as the basis for a
057:         * specific JSSE listener.
058:         * 
059:         * This is heavily based on the work from Court Demas, which in turn is based on the work from Forge
060:         * Research.
061:         * 
062:         * @author Greg Wilkins (gregw@mortbay.com)
063:         * @author Court Demas (court@kiwiconsulting.com)
064:         * @author Forge Research Pty Ltd ACN 003 491 576
065:         * @author Jan Hlavat�
066:         */
067:        public class SslSocketConnector extends SocketConnector {
068:            /**
069:             * The name of the SSLSession attribute that will contain any cached information.
070:             */
071:            static final String CACHED_INFO_ATTR = CachedInfo.class.getName();
072:
073:            /** String name of key password property. */
074:            public static final String KEYPASSWORD_PROPERTY = "jetty.ssl.keypassword";
075:
076:            /** String name of keystore password property. */
077:            public static final String PASSWORD_PROPERTY = "jetty.ssl.password";
078:
079:            /**
080:             * Return the chain of X509 certificates used to negotiate the SSL Session.
081:             * <p>
082:             * Note: in order to do this we must convert a javax.security.cert.X509Certificate[], as used by
083:             * JSSE to a java.security.cert.X509Certificate[],as required by the Servlet specs.
084:             * 
085:             * @param sslSession the javax.net.ssl.SSLSession to use as the source of the cert chain.
086:             * @return the chain of java.security.cert.X509Certificates used to negotiate the SSL
087:             *         connection. <br>
088:             *         Will be null if the chain is missing or empty.
089:             */
090:            private static X509Certificate[] getCertChain(SSLSession sslSession) {
091:                try {
092:                    javax.security.cert.X509Certificate javaxCerts[] = sslSession
093:                            .getPeerCertificateChain();
094:                    if (javaxCerts == null || javaxCerts.length == 0)
095:                        return null;
096:
097:                    int length = javaxCerts.length;
098:                    X509Certificate[] javaCerts = new X509Certificate[length];
099:
100:                    java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory
101:                            .getInstance("X.509");
102:                    for (int i = 0; i < length; i++) {
103:                        byte bytes[] = javaxCerts[i].getEncoded();
104:                        ByteArrayInputStream stream = new ByteArrayInputStream(
105:                                bytes);
106:                        javaCerts[i] = (X509Certificate) cf
107:                                .generateCertificate(stream);
108:                    }
109:
110:                    return javaCerts;
111:                } catch (SSLPeerUnverifiedException pue) {
112:                    return null;
113:                } catch (Exception e) {
114:                    Log.warn(Log.EXCEPTION, e);
115:                    return null;
116:                }
117:            }
118:
119:            /** Default value for the cipher Suites. */
120:            private String _excludeCipherSuites[] = null;
121:
122:            private String _keystore = null;
123:            private String _keystoreType = "JKS"; // type of the key store
124:
125:            /** Set to true if we require client certificate authentication. */
126:            private boolean _needClientAuth = false;
127:            private transient Password _password;
128:            private transient Password _keyPassword;
129:            private transient Password _trustPassword;
130:            private String _protocol = "TLS";
131:            private String _provider;
132:            private String _secureRandomAlgorithm; // cert algorithm
133:            private String _sslKeyManagerFactoryAlgorithm = (Security
134:                    .getProperty("ssl.KeyManagerFactory.algorithm") == null ? "SunX509"
135:                    : Security.getProperty("ssl.KeyManagerFactory.algorithm")); // cert algorithm
136:            private String _sslTrustManagerFactoryAlgorithm = (Security
137:                    .getProperty("ssl.TrustManagerFactory.algorithm") == null ? "SunX509"
138:                    : Security.getProperty("ssl.TrustManagerFactory.algorithm")); // cert algorithm
139:
140:            private String _truststore;
141:            private String _truststoreType = "JKS"; // type of the key store
142:
143:            /** Set to true if we would like client certificate authentication. */
144:            private boolean _wantClientAuth = false;
145:
146:            /* ------------------------------------------------------------ */
147:            /**
148:             * Constructor.
149:             */
150:            public SslSocketConnector() {
151:                super ();
152:            }
153:
154:            /* ------------------------------------------------------------ */
155:            protected void configure(Socket socket) throws IOException {
156:                super .configure(socket);
157:
158:                ((SSLSocket) socket).startHandshake(); // block until SSL handshaking is done
159:            }
160:
161:            /* ------------------------------------------------------------ */
162:            protected SSLServerSocketFactory createFactory() throws Exception {
163:                if (_password == null)
164:                    _password = new Password("");
165:                if (_keyPassword == null)
166:                    _keyPassword = _password;
167:                if (_trustPassword == null)
168:                    _trustPassword = _password;
169:
170:                KeyManager[] keyManagers = null;
171:                if (_keystore != null) {
172:                    KeyStore keyStore = KeyStore.getInstance(_keystoreType);
173:                    if (_password == null)
174:                        throw new SSLException("_password is not set");
175:                    keyStore.load(Resource.newResource(_keystore)
176:                            .getInputStream(), _password.toString()
177:                            .toCharArray());
178:
179:                    KeyManagerFactory keyManagerFactory = KeyManagerFactory
180:                            .getInstance(_sslKeyManagerFactoryAlgorithm);
181:                    if (_keyPassword == null)
182:                        throw new SSLException("_keypassword is not set");
183:                    keyManagerFactory.init(keyStore, _keyPassword.toString()
184:                            .toCharArray());
185:                    keyManagers = keyManagerFactory.getKeyManagers();
186:                }
187:
188:                TrustManager[] trustManagers = null;
189:                if (_truststore != null) {
190:                    KeyStore trustStore = KeyStore.getInstance(_truststoreType);
191:                    trustStore.load(Resource.newResource(_truststore)
192:                            .getInputStream(), _trustPassword.toString()
193:                            .toCharArray());
194:
195:                    TrustManagerFactory trustManagerFactory = TrustManagerFactory
196:                            .getInstance(_sslTrustManagerFactoryAlgorithm);
197:                    trustManagerFactory.init(trustStore);
198:                    trustManagers = trustManagerFactory.getTrustManagers();
199:                }
200:
201:                SecureRandom secureRandom = _secureRandomAlgorithm == null ? null
202:                        : SecureRandom.getInstance(_secureRandomAlgorithm);
203:
204:                SSLContext context = _provider == null ? SSLContext
205:                        .getInstance(_protocol) : SSLContext.getInstance(
206:                        _protocol, _provider);
207:
208:                context.init(keyManagers, trustManagers, secureRandom);
209:
210:                return context.getServerSocketFactory();
211:            }
212:
213:            /* ------------------------------------------------------------ */
214:            /**
215:             * Allow the Listener a chance to customise the request. before the server does its stuff. <br>
216:             * This allows the required attributes to be set for SSL requests. <br>
217:             * The requirements of the Servlet specs are:
218:             * <ul>
219:             * <li> an attribute named "javax.servlet.request.cipher_suite" of type String.</li>
220:             * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
221:             * <li> an attribute named "javax.servlet.request.X509Certificate" of type
222:             * java.security.cert.X509Certificate[]. This is an array of objects of type X509Certificate,
223:             * the order of this array is defined as being in ascending order of trust. The first
224:             * certificate in the chain is the one set by the client, the next is the one used to
225:             * authenticate the first, and so on. </li>
226:             * </ul>
227:             * 
228:             * @param endpoint The Socket the request arrived on. 
229:             *        This should be a {@link SocketEndPoint} wrapping a {@link SSLSocket}.
230:             * @param request HttpRequest to be customised.
231:             */
232:            public void customize(EndPoint endpoint, Request request)
233:                    throws IOException {
234:                super .customize(endpoint, request);
235:                request.setScheme(HttpSchemes.HTTPS);
236:
237:                SocketEndPoint socket_end_point = (SocketEndPoint) endpoint;
238:                SSLSocket sslSocket = (SSLSocket) socket_end_point
239:                        .getTransport();
240:
241:                try {
242:                    SSLSession sslSession = sslSocket.getSession();
243:                    String cipherSuite = sslSession.getCipherSuite();
244:                    Integer keySize;
245:                    X509Certificate[] certs;
246:
247:                    CachedInfo cachedInfo = (CachedInfo) sslSession
248:                            .getValue(CACHED_INFO_ATTR);
249:                    if (cachedInfo != null) {
250:                        keySize = cachedInfo.getKeySize();
251:                        certs = cachedInfo.getCerts();
252:                    } else {
253:                        keySize = new Integer(ServletSSL
254:                                .deduceKeyLength(cipherSuite));
255:                        certs = getCertChain(sslSession);
256:                        cachedInfo = new CachedInfo(keySize, certs);
257:                        sslSession.putValue(CACHED_INFO_ATTR, cachedInfo);
258:                    }
259:
260:                    if (certs != null)
261:                        request.setAttribute(
262:                                "javax.servlet.request.X509Certificate", certs);
263:                    else if (_needClientAuth) // Sanity check
264:                        throw new IllegalStateException("no client auth");
265:
266:                    request.setAttribute("javax.servlet.request.cipher_suite",
267:                            cipherSuite);
268:                    request.setAttribute("javax.servlet.request.key_size",
269:                            keySize);
270:                } catch (Exception e) {
271:                    Log.warn(Log.EXCEPTION, e);
272:                }
273:            }
274:
275:            /* ------------------------------------------------------------ */
276:            public String[] getExcludeCipherSuites() {
277:                return _excludeCipherSuites;
278:            }
279:
280:            /* ------------------------------------------------------------ */
281:            public String getKeystore() {
282:                return _keystore;
283:            }
284:
285:            /* ------------------------------------------------------------ */
286:            public String getKeystoreType() {
287:                return (_keystoreType);
288:            }
289:
290:            /* ------------------------------------------------------------ */
291:            public boolean getNeedClientAuth() {
292:                return _needClientAuth;
293:            }
294:
295:            /* ------------------------------------------------------------ */
296:            public String getProtocol() {
297:                return _protocol;
298:            }
299:
300:            /* ------------------------------------------------------------ */
301:            public String getProvider() {
302:                return _provider;
303:            }
304:
305:            /* ------------------------------------------------------------ */
306:            public String getSecureRandomAlgorithm() {
307:                return (this ._secureRandomAlgorithm);
308:            }
309:
310:            /* ------------------------------------------------------------ */
311:            public String getSslKeyManagerFactoryAlgorithm() {
312:                return (this ._sslKeyManagerFactoryAlgorithm);
313:            }
314:
315:            /* ------------------------------------------------------------ */
316:            public String getSslTrustManagerFactoryAlgorithm() {
317:                return (this ._sslTrustManagerFactoryAlgorithm);
318:            }
319:
320:            /* ------------------------------------------------------------ */
321:            public String getTruststore() {
322:                return _truststore;
323:            }
324:
325:            /* ------------------------------------------------------------ */
326:            public String getTruststoreType() {
327:                return _truststoreType;
328:            }
329:
330:            /* ------------------------------------------------------------ */
331:            public boolean getWantClientAuth() {
332:                return _wantClientAuth;
333:            }
334:
335:            /* ------------------------------------------------------------ */
336:            /**
337:             * By default, we're confidential, given we speak SSL. But, if we've been told about an
338:             * confidential port, and said port is not our port, then we're not. This allows separation of
339:             * listeners providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener
340:             * configured to require client certs providing CONFIDENTIAL, whereas another SSL listener not
341:             * requiring client certs providing mere INTEGRAL constraints.
342:             */
343:            public boolean isConfidential(Request request) {
344:                final int confidentialPort = getConfidentialPort();
345:                return confidentialPort == 0
346:                        || confidentialPort == request.getServerPort();
347:            }
348:
349:            /* ------------------------------------------------------------ */
350:            /**
351:             * By default, we're integral, given we speak SSL. But, if we've been told about an integral
352:             * port, and said port is not our port, then we're not. This allows separation of listeners
353:             * providing INTEGRAL versus CONFIDENTIAL constraints, such as one SSL listener configured to
354:             * require client certs providing CONFIDENTIAL, whereas another SSL listener not requiring
355:             * client certs providing mere INTEGRAL constraints.
356:             */
357:            public boolean isIntegral(Request request) {
358:                final int integralPort = getIntegralPort();
359:                return integralPort == 0
360:                        || integralPort == request.getServerPort();
361:            }
362:
363:            /* ------------------------------------------------------------ */
364:            /**
365:             * @param addr The {@link SocketAddress address} that this server should listen on 
366:             * @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)}
367:             * @return A new {@link ServerSocket socket object} bound to the supplied address with all other
368:             * settings as per the current configuration of this connector. 
369:             * @see #setWantClientAuth
370:             * @see #setNeedClientAuth
371:             * @see #setCipherSuites
372:             * @exception IOException
373:             */
374:
375:            /* ------------------------------------------------------------ */
376:            protected ServerSocket newServerSocket(String host, int port,
377:                    int backlog) throws IOException {
378:                SSLServerSocketFactory factory = null;
379:                SSLServerSocket socket = null;
380:
381:                try {
382:                    factory = createFactory();
383:
384:                    socket = (SSLServerSocket) (host == null ? factory
385:                            .createServerSocket(port, backlog) : factory
386:                            .createServerSocket(port, backlog, InetAddress
387:                                    .getByName(host)));
388:
389:                    if (_wantClientAuth)
390:                        socket.setWantClientAuth(_wantClientAuth);
391:                    if (_needClientAuth)
392:                        socket.setNeedClientAuth(_needClientAuth);
393:
394:                    if (_excludeCipherSuites != null
395:                            && _excludeCipherSuites.length > 0) {
396:                        List excludedCSList = Arrays
397:                                .asList(_excludeCipherSuites);
398:                        String[] enabledCipherSuites = socket
399:                                .getEnabledCipherSuites();
400:                        List enabledCSList = new ArrayList(Arrays
401:                                .asList(enabledCipherSuites));
402:                        Iterator exIter = excludedCSList.iterator();
403:
404:                        while (exIter.hasNext()) {
405:                            String cipherName = (String) exIter.next();
406:                            if (enabledCSList.contains(cipherName)) {
407:                                enabledCSList.remove(cipherName);
408:                            }
409:                        }
410:                        enabledCipherSuites = (String[]) enabledCSList
411:                                .toArray(new String[enabledCSList.size()]);
412:
413:                        socket.setEnabledCipherSuites(enabledCipherSuites);
414:                    }
415:
416:                } catch (IOException e) {
417:                    throw e;
418:                } catch (Exception e) {
419:                    Log.warn(Log.EXCEPTION, e);
420:                    throw new IOException("Could not create JsseListener: "
421:                            + e.toString());
422:                }
423:                return socket;
424:            }
425:
426:            /* ------------------------------------------------------------ */
427:            /** 
428:             * @author Tony Jiang
429:             */
430:            public void setExcludeCipherSuites(String[] cipherSuites) {
431:                this ._excludeCipherSuites = cipherSuites;
432:            }
433:
434:            /* ------------------------------------------------------------ */
435:            public void setKeyPassword(String password) {
436:                _keyPassword = Password.getPassword(KEYPASSWORD_PROPERTY,
437:                        password, null);
438:            }
439:
440:            /* ------------------------------------------------------------ */
441:            public void setKeystore(String keystore) {
442:                _keystore = keystore;
443:            }
444:
445:            /* ------------------------------------------------------------ */
446:            public void setKeystoreType(String keystoreType) {
447:                _keystoreType = keystoreType;
448:            }
449:
450:            /* ------------------------------------------------------------ */
451:            /**
452:             * Set the value of the needClientAuth property
453:             * 
454:             * @param needClientAuth true iff we require client certificate authentication.
455:             */
456:            public void setNeedClientAuth(boolean needClientAuth) {
457:                _needClientAuth = needClientAuth;
458:            }
459:
460:            /* ------------------------------------------------------------ */
461:            public void setPassword(String password) {
462:                _password = Password.getPassword(PASSWORD_PROPERTY, password,
463:                        null);
464:            }
465:
466:            /* ------------------------------------------------------------ */
467:            public void setTrustPassword(String password) {
468:                _trustPassword = Password.getPassword(PASSWORD_PROPERTY,
469:                        password, null);
470:            }
471:
472:            /* ------------------------------------------------------------ */
473:            public void setProtocol(String protocol) {
474:                _protocol = protocol;
475:            }
476:
477:            /* ------------------------------------------------------------ */
478:            public void setProvider(String _provider) {
479:                this ._provider = _provider;
480:            }
481:
482:            /* ------------------------------------------------------------ */
483:            public void setSecureRandomAlgorithm(String algorithm) {
484:                this ._secureRandomAlgorithm = algorithm;
485:            }
486:
487:            /* ------------------------------------------------------------ */
488:            public void setSslKeyManagerFactoryAlgorithm(String algorithm) {
489:                this ._sslKeyManagerFactoryAlgorithm = algorithm;
490:            }
491:
492:            /* ------------------------------------------------------------ */
493:            public void setSslTrustManagerFactoryAlgorithm(String algorithm) {
494:                this ._sslTrustManagerFactoryAlgorithm = algorithm;
495:            }
496:
497:            public void setTruststore(String truststore) {
498:                _truststore = truststore;
499:            }
500:
501:            public void setTruststoreType(String truststoreType) {
502:                _truststoreType = truststoreType;
503:            }
504:
505:            /* ------------------------------------------------------------ */
506:            /**
507:             * Set the value of the _wantClientAuth property. This property is used when
508:             * {@link #newServerSocket(SocketAddress, int) opening server sockets}.
509:             * 
510:             * @param wantClientAuth true iff we want client certificate authentication.
511:             * @see SSLServerSocket#setWantClientAuth
512:             */
513:            public void setWantClientAuth(boolean wantClientAuth) {
514:                _wantClientAuth = wantClientAuth;
515:            }
516:
517:            /**
518:             * Simple bundle of information that is cached in the SSLSession. Stores the effective keySize
519:             * and the client certificate chain.
520:             */
521:            private class CachedInfo {
522:                private X509Certificate[] _certs;
523:                private Integer _keySize;
524:
525:                CachedInfo(Integer keySize, X509Certificate[] certs) {
526:                    this ._keySize = keySize;
527:                    this ._certs = certs;
528:                }
529:
530:                X509Certificate[] getCerts() {
531:                    return _certs;
532:                }
533:
534:                Integer getKeySize() {
535:                    return _keySize;
536:                }
537:            }
538:
539:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.