~ubuntu-branches/ubuntu/utopic/jetty/utopic-proposed

« back to all changes in this revision

Viewing changes to extras/sslengine/src/main/java/org/mortbay/jetty/security/SslSelectChannelConnector.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2009-08-09 08:48:10 UTC
  • Revision ID: james.westby@ubuntu.com-20090809084810-k522b97ind2robyd
ImportĀ upstreamĀ versionĀ 6.1.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
 
3
//------------------------------------------------------------------------
 
4
//Licensed under the Apache License, Version 2.0 (the "License");
 
5
//you may not use this file except in compliance with the License.
 
6
//You may obtain a copy of the License at 
 
7
//http://www.apache.org/licenses/LICENSE-2.0
 
8
//Unless required by applicable law or agreed to in writing, software
 
9
//distributed under the License is distributed on an "AS IS" BASIS,
 
10
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
11
//See the License for the specific language governing permissions and
 
12
//limitations under the License.
 
13
//========================================================================
 
14
 
 
15
package org.mortbay.jetty.security;
 
16
 
 
17
import java.io.ByteArrayInputStream;
 
18
import java.io.File;
 
19
import java.io.IOException;
 
20
import java.io.InputStream;
 
21
import java.nio.ByteBuffer;
 
22
import java.nio.channels.SelectionKey;
 
23
import java.nio.channels.SocketChannel;
 
24
import java.security.KeyStore;
 
25
import java.security.SecureRandom;
 
26
import java.security.Security;
 
27
import java.security.cert.X509Certificate;
 
28
import java.util.ArrayList;
 
29
import java.util.Arrays;
 
30
import java.util.List;
 
31
import java.util.concurrent.ConcurrentLinkedQueue;
 
32
 
 
33
import javax.net.ssl.KeyManager;
 
34
import javax.net.ssl.KeyManagerFactory;
 
35
import javax.net.ssl.SSLContext;
 
36
import javax.net.ssl.SSLEngine;
 
37
import javax.net.ssl.SSLPeerUnverifiedException;
 
38
import javax.net.ssl.SSLSession;
 
39
import javax.net.ssl.SSLSocket;
 
40
import javax.net.ssl.TrustManager;
 
41
import javax.net.ssl.TrustManagerFactory;
 
42
 
 
43
import org.mortbay.io.Buffer;
 
44
import org.mortbay.io.Connection;
 
45
import org.mortbay.io.EndPoint;
 
46
import org.mortbay.io.bio.SocketEndPoint;
 
47
import org.mortbay.io.nio.DirectNIOBuffer;
 
48
import org.mortbay.io.nio.IndirectNIOBuffer;
 
49
import org.mortbay.io.nio.NIOBuffer;
 
50
import org.mortbay.io.nio.SelectChannelEndPoint;
 
51
import org.mortbay.io.nio.SelectorManager.SelectSet;
 
52
import org.mortbay.jetty.HttpConnection;
 
53
import org.mortbay.jetty.HttpParser;
 
54
import org.mortbay.jetty.HttpSchemes;
 
55
import org.mortbay.jetty.Request;
 
56
import org.mortbay.jetty.nio.SelectChannelConnector;
 
57
import org.mortbay.log.Log;
 
58
import org.mortbay.resource.Resource;
 
59
 
 
60
/* ------------------------------------------------------------ */
 
61
/**
 
62
 * SslSelectChannelConnector.
 
63
 * 
 
64
 * @author Nik Gonzalez <ngonzalez@exist.com>
 
65
 * @author Greg Wilkins <gregw@mortbay.com>
 
66
 */
 
67
public class SslSelectChannelConnector extends SelectChannelConnector
 
68
{
 
69
    /**
 
70
     * The name of the SSLSession attribute that will contain any cached
 
71
     * information.
 
72
     */
 
73
    static final String CACHED_INFO_ATTR=CachedInfo.class.getName();
 
74
 
 
75
    /** Default value for the keystore location path. */
 
76
    public static final String DEFAULT_KEYSTORE=System.getProperty("user.home")+File.separator+".keystore";
 
77
 
 
78
    /** String name of key password property. */
 
79
    public static final String KEYPASSWORD_PROPERTY="jetty.ssl.keypassword";
 
80
 
 
81
    /** String name of keystore password property. */
 
82
    public static final String PASSWORD_PROPERTY="jetty.ssl.password";
 
83
 
 
84
    /** Default value for the cipher Suites. */
 
85
    private String _excludeCipherSuites[]=null;
 
86
 
 
87
    /** Default value for the keystore location path. */
 
88
    private String _keystore=DEFAULT_KEYSTORE;
 
89
    private String _keystoreType="JKS"; // type of the key store
 
90
 
 
91
    /** Set to true if we require client certificate authentication. */
 
92
    private boolean _needClientAuth=false;
 
93
    private boolean _wantClientAuth=false;
 
94
 
 
95
    private transient Password _password;
 
96
    private transient Password _keyPassword;
 
97
    private transient Password _trustPassword;
 
98
    private String _protocol="TLS";
 
99
    private String _algorithm="SunX509"; // cert algorithm
 
100
    private String _provider;
 
101
    private String _secureRandomAlgorithm; // cert algorithm
 
102
    private String _sslKeyManagerFactoryAlgorithm=(Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security
 
103
            .getProperty("ssl.KeyManagerFactory.algorithm")); // cert
 
104
                                                                // algorithm
 
105
 
 
106
    private String _sslTrustManagerFactoryAlgorithm=(Security.getProperty("ssl.TrustManagerFactory.algorithm")==null?"SunX509":Security
 
107
            .getProperty("ssl.TrustManagerFactory.algorithm")); // cert
 
108
                                                                // algorithm
 
109
 
 
110
    private String _truststore;
 
111
    private String _truststoreType="JKS"; // type of the key store
 
112
    private SSLContext _context;
 
113
 
 
114
    private int _packetBufferSize;
 
115
    private int _applicationBufferSize;
 
116
    private ConcurrentLinkedQueue<Buffer> _packetBuffers = new ConcurrentLinkedQueue<Buffer>();
 
117
    private ConcurrentLinkedQueue<Buffer> _applicationBuffers = new ConcurrentLinkedQueue<Buffer>();
 
118
    
 
119
    /* ------------------------------------------------------------ */
 
120
    /* (non-Javadoc)
 
121
     * @see org.mortbay.jetty.AbstractBuffers#getBuffer(int)
 
122
     */
 
123
    public Buffer getBuffer(int size)
 
124
    {
 
125
        Buffer buffer;
 
126
        if (size==_applicationBufferSize)
 
127
        {   
 
128
            buffer = _applicationBuffers.poll();
 
129
            if (buffer==null)
 
130
                buffer=new IndirectNIOBuffer(size); 
 
131
        }
 
132
        else if (size==_packetBufferSize)
 
133
        {   
 
134
            buffer = _packetBuffers.poll();
 
135
            if (buffer==null)
 
136
                buffer=getUseDirectBuffers()
 
137
                    ?(NIOBuffer)new DirectNIOBuffer(size)
 
138
                    :(NIOBuffer)new IndirectNIOBuffer(size);
 
139
        }
 
140
        else 
 
141
            buffer=super.getBuffer(size);
 
142
        
 
143
        return buffer;
 
144
    }
 
145
    
 
146
 
 
147
    /* ------------------------------------------------------------ */
 
148
    /* (non-Javadoc)
 
149
     * @see org.mortbay.jetty.AbstractBuffers#returnBuffer(org.mortbay.io.Buffer)
 
150
     */
 
151
    public void returnBuffer(Buffer buffer)
 
152
    {
 
153
        buffer.clear();
 
154
        int size=buffer.capacity();
 
155
        ByteBuffer bbuf = ((NIOBuffer)buffer).getByteBuffer();
 
156
        bbuf.position(0);
 
157
        bbuf.limit(size);
 
158
        
 
159
        if (size==_applicationBufferSize)
 
160
            _applicationBuffers.add(buffer);
 
161
        else if (size==_packetBufferSize)
 
162
            _packetBuffers.add(buffer);
 
163
        else 
 
164
            super.returnBuffer(buffer);
 
165
    }
 
166
    
 
167
    
 
168
 
 
169
    /**
 
170
     * Return the chain of X509 certificates used to negotiate the SSL Session.
 
171
     * <p>
 
172
     * Note: in order to do this we must convert a
 
173
     * javax.security.cert.X509Certificate[], as used by JSSE to a
 
174
     * java.security.cert.X509Certificate[],as required by the Servlet specs.
 
175
     * 
 
176
     * @param sslSession
 
177
     *                the javax.net.ssl.SSLSession to use as the source of the
 
178
     *                cert chain.
 
179
     * @return the chain of java.security.cert.X509Certificates used to
 
180
     *         negotiate the SSL connection. <br>
 
181
     *         Will be null if the chain is missing or empty.
 
182
     */
 
183
    private static X509Certificate[] getCertChain(SSLSession sslSession)
 
184
    {
 
185
        try
 
186
        {
 
187
            javax.security.cert.X509Certificate javaxCerts[]=sslSession.getPeerCertificateChain();
 
188
            if (javaxCerts==null||javaxCerts.length==0)
 
189
                return null;
 
190
 
 
191
            int length=javaxCerts.length;
 
192
            X509Certificate[] javaCerts=new X509Certificate[length];
 
193
 
 
194
            java.security.cert.CertificateFactory cf=java.security.cert.CertificateFactory.getInstance("X.509");
 
195
            for (int i=0; i<length; i++)
 
196
            {
 
197
                byte bytes[]=javaxCerts[i].getEncoded();
 
198
                ByteArrayInputStream stream=new ByteArrayInputStream(bytes);
 
199
                javaCerts[i]=(X509Certificate)cf.generateCertificate(stream);
 
200
            }
 
201
 
 
202
            return javaCerts;
 
203
        }
 
204
        catch (SSLPeerUnverifiedException e)
 
205
        {
 
206
            Log.ignore(e);
 
207
            return null;
 
208
        }
 
209
        catch (Exception e)
 
210
        {
 
211
            Log.warn(Log.EXCEPTION,e);
 
212
            return null;
 
213
        }
 
214
    }
 
215
 
 
216
    /* ------------------------------------------------------------ */
 
217
    /**
 
218
     * Allow the Listener a chance to customise the request. before the server
 
219
     * does its stuff. <br>
 
220
     * This allows the required attributes to be set for SSL requests. <br>
 
221
     * The requirements of the Servlet specs are:
 
222
     * <ul>
 
223
     * <li> an attribute named "javax.servlet.request.cipher_suite" of type
 
224
     * String.</li>
 
225
     * <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
 
226
     * <li> an attribute named "javax.servlet.request.X509Certificate" of type
 
227
     * java.security.cert.X509Certificate[]. This is an array of objects of type
 
228
     * X509Certificate, the order of this array is defined as being in ascending
 
229
     * order of trust. The first certificate in the chain is the one set by the
 
230
     * client, the next is the one used to authenticate the first, and so on.
 
231
     * </li>
 
232
     * </ul>
 
233
     * 
 
234
     * @param endpoint
 
235
     *                The Socket the request arrived on. This should be a
 
236
     *                {@link SocketEndPoint} wrapping a {@link SSLSocket}.
 
237
     * @param request
 
238
     *                HttpRequest to be customised.
 
239
     */
 
240
    public void customize(EndPoint endpoint, Request request) throws IOException
 
241
    {
 
242
        super.customize(endpoint,request);
 
243
        request.setScheme(HttpSchemes.HTTPS);
 
244
        
 
245
        SslHttpChannelEndPoint sslHttpChannelEndpoint=(SslHttpChannelEndPoint)endpoint;
 
246
        SSLEngine sslEngine=sslHttpChannelEndpoint.getSSLEngine();
 
247
 
 
248
        try
 
249
        {
 
250
            SSLSession sslSession=sslEngine.getSession();
 
251
            String cipherSuite=sslSession.getCipherSuite();
 
252
            Integer keySize;
 
253
            X509Certificate[] certs;
 
254
 
 
255
            CachedInfo cachedInfo=(CachedInfo)sslSession.getValue(CACHED_INFO_ATTR);
 
256
            if (cachedInfo!=null)
 
257
            {
 
258
                keySize=cachedInfo.getKeySize();
 
259
                certs=cachedInfo.getCerts();
 
260
            }
 
261
            else
 
262
            {
 
263
                keySize=new Integer(ServletSSL.deduceKeyLength(cipherSuite));
 
264
                certs=getCertChain(sslSession);
 
265
                cachedInfo=new CachedInfo(keySize,certs);
 
266
                sslSession.putValue(CACHED_INFO_ATTR,cachedInfo);
 
267
            }
 
268
 
 
269
            if (certs!=null)
 
270
                request.setAttribute("javax.servlet.request.X509Certificate",certs);
 
271
 
 
272
            request.setAttribute("javax.servlet.request.cipher_suite",cipherSuite);
 
273
            request.setAttribute("javax.servlet.request.key_size",keySize);
 
274
        }
 
275
        catch (Exception e)
 
276
        {
 
277
            Log.warn(Log.EXCEPTION,e);
 
278
        }
 
279
    }
 
280
 
 
281
    /* ------------------------------------------------------------ */
 
282
    public SslSelectChannelConnector()
 
283
    {
 
284
        // Buffer sizes should be from SSL session, but not known at this stage.
 
285
        // size should be 16k, but appears to need 16k+1 byte? Giving it 16k+2k
 
286
        // just
 
287
        // to be safe. TODO investigate
 
288
        
 
289
    }
 
290
 
 
291
    /**
 
292
     * 
 
293
     * @deprecated As of Java Servlet API 2.0, with no replacement.
 
294
     * 
 
295
     */
 
296
    public String[] getCipherSuites()
 
297
    {
 
298
        return getExcludeCipherSuites();
 
299
    }
 
300
 
 
301
    public String[] getExcludeCipherSuites()
 
302
    {
 
303
        return _excludeCipherSuites;
 
304
    }
 
305
 
 
306
    /**
 
307
     * 
 
308
     * @deprecated As of Java Servlet API 2.0, with no replacement.
 
309
     * 
 
310
     * @author Tony Jiang
 
311
     */
 
312
    public void setCipherSuites(String[] cipherSuites)
 
313
    {
 
314
        setExcludeCipherSuites(cipherSuites);
 
315
    }
 
316
 
 
317
    public void setExcludeCipherSuites(String[] cipherSuites)
 
318
    {
 
319
        this._excludeCipherSuites=cipherSuites;
 
320
    }
 
321
 
 
322
    /* ------------------------------------------------------------ */
 
323
    public void setPassword(String password)
 
324
    {
 
325
        _password=Password.getPassword(PASSWORD_PROPERTY,password,null);
 
326
    }
 
327
 
 
328
    /* ------------------------------------------------------------ */
 
329
    public void setTrustPassword(String password)
 
330
    {
 
331
        _trustPassword=Password.getPassword(PASSWORD_PROPERTY,password,null);
 
332
    }
 
333
 
 
334
    /* ------------------------------------------------------------ */
 
335
    public void setKeyPassword(String password)
 
336
    {
 
337
        _keyPassword=Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
 
338
    }
 
339
 
 
340
    /* ------------------------------------------------------------ */
 
341
    public String getAlgorithm()
 
342
    {
 
343
        return (this._algorithm);
 
344
    }
 
345
 
 
346
    /* ------------------------------------------------------------ */
 
347
    public void setAlgorithm(String algorithm)
 
348
    {
 
349
        this._algorithm=algorithm;
 
350
    }
 
351
 
 
352
    /* ------------------------------------------------------------ */
 
353
    public String getProtocol()
 
354
    {
 
355
        return _protocol;
 
356
    }
 
357
 
 
358
    /* ------------------------------------------------------------ */
 
359
    public void setProtocol(String protocol)
 
360
    {
 
361
        _protocol=protocol;
 
362
    }
 
363
 
 
364
    /* ------------------------------------------------------------ */
 
365
    public void setKeystore(String keystore)
 
366
    {
 
367
        _keystore=keystore;
 
368
    }
 
369
 
 
370
    /* ------------------------------------------------------------ */
 
371
    public String getKeystore()
 
372
    {
 
373
        return _keystore;
 
374
    }
 
375
 
 
376
    /* ------------------------------------------------------------ */
 
377
    public String getKeystoreType()
 
378
    {
 
379
        return (_keystoreType);
 
380
    }
 
381
 
 
382
    /* ------------------------------------------------------------ */
 
383
    public boolean getNeedClientAuth()
 
384
    {
 
385
        return _needClientAuth;
 
386
    }
 
387
 
 
388
    /* ------------------------------------------------------------ */
 
389
    public boolean getWantClientAuth()
 
390
    {
 
391
        return _wantClientAuth;
 
392
    }
 
393
 
 
394
    /* ------------------------------------------------------------ */
 
395
    /**
 
396
     * Set the value of the needClientAuth property
 
397
     * 
 
398
     * @param needClientAuth
 
399
     *                true iff we require client certificate authentication.
 
400
     */
 
401
    public void setNeedClientAuth(boolean needClientAuth)
 
402
    {
 
403
        _needClientAuth=needClientAuth;
 
404
    }
 
405
 
 
406
    public void setWantClientAuth(boolean wantClientAuth)
 
407
    {
 
408
        _wantClientAuth=wantClientAuth;
 
409
    }
 
410
 
 
411
    /* ------------------------------------------------------------ */
 
412
    public void setKeystoreType(String keystoreType)
 
413
    {
 
414
        _keystoreType=keystoreType;
 
415
    }
 
416
 
 
417
    /* ------------------------------------------------------------ */
 
418
    public String getProvider()
 
419
    {
 
420
        return _provider;
 
421
    }
 
422
 
 
423
    public String getSecureRandomAlgorithm()
 
424
    {
 
425
        return (this._secureRandomAlgorithm);
 
426
    }
 
427
 
 
428
    /* ------------------------------------------------------------ */
 
429
    public String getSslKeyManagerFactoryAlgorithm()
 
430
    {
 
431
        return (this._sslKeyManagerFactoryAlgorithm);
 
432
    }
 
433
 
 
434
    /* ------------------------------------------------------------ */
 
435
    public String getSslTrustManagerFactoryAlgorithm()
 
436
    {
 
437
        return (this._sslTrustManagerFactoryAlgorithm);
 
438
    }
 
439
 
 
440
    /* ------------------------------------------------------------ */
 
441
    public String getTruststore()
 
442
    {
 
443
        return _truststore;
 
444
    }
 
445
 
 
446
    /* ------------------------------------------------------------ */
 
447
    public String getTruststoreType()
 
448
    {
 
449
        return _truststoreType;
 
450
    }
 
451
 
 
452
    /* ------------------------------------------------------------ */
 
453
    public void setProvider(String _provider)
 
454
    {
 
455
        this._provider=_provider;
 
456
    }
 
457
 
 
458
    /* ------------------------------------------------------------ */
 
459
    public void setSecureRandomAlgorithm(String algorithm)
 
460
    {
 
461
        this._secureRandomAlgorithm=algorithm;
 
462
    }
 
463
 
 
464
    /* ------------------------------------------------------------ */
 
465
    public void setSslKeyManagerFactoryAlgorithm(String algorithm)
 
466
    {
 
467
        this._sslKeyManagerFactoryAlgorithm=algorithm;
 
468
    }
 
469
 
 
470
    /* ------------------------------------------------------------ */
 
471
    public void setSslTrustManagerFactoryAlgorithm(String algorithm)
 
472
    {
 
473
        this._sslTrustManagerFactoryAlgorithm=algorithm;
 
474
    }
 
475
 
 
476
    public void setTruststore(String truststore)
 
477
    {
 
478
        _truststore=truststore;
 
479
    }
 
480
 
 
481
    public void setTruststoreType(String truststoreType)
 
482
    {
 
483
        _truststoreType=truststoreType;
 
484
    }
 
485
 
 
486
    /* ------------------------------------------------------------ */
 
487
    /**
 
488
     * By default, we're confidential, given we speak SSL. But, if we've been
 
489
     * told about an confidential port, and said port is not our port, then
 
490
     * we're not. This allows separation of listeners providing INTEGRAL versus
 
491
     * CONFIDENTIAL constraints, such as one SSL listener configured to require
 
492
     * client certs providing CONFIDENTIAL, whereas another SSL listener not
 
493
     * requiring client certs providing mere INTEGRAL constraints.
 
494
     */
 
495
    public boolean isConfidential(Request request)
 
496
    {
 
497
        final int confidentialPort=getConfidentialPort();
 
498
        return confidentialPort==0||confidentialPort==request.getServerPort();
 
499
    }
 
500
 
 
501
    /* ------------------------------------------------------------ */
 
502
    /**
 
503
     * By default, we're integral, given we speak SSL. But, if we've been told
 
504
     * about an integral port, and said port is not our port, then we're not.
 
505
     * This allows separation of listeners providing INTEGRAL versus
 
506
     * CONFIDENTIAL constraints, such as one SSL listener configured to require
 
507
     * client certs providing CONFIDENTIAL, whereas another SSL listener not
 
508
     * requiring client certs providing mere INTEGRAL constraints.
 
509
     */
 
510
    public boolean isIntegral(Request request)
 
511
    {
 
512
        final int integralPort=getIntegralPort();
 
513
        return integralPort==0||integralPort==request.getServerPort();
 
514
    }
 
515
 
 
516
    /* ------------------------------------------------------------------------------- */
 
517
    protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
 
518
    {
 
519
        return new SslHttpChannelEndPoint(this,channel,selectSet,key,createSSLEngine());
 
520
    }
 
521
 
 
522
    /* ------------------------------------------------------------------------------- */
 
523
    protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
 
524
    {
 
525
        HttpConnection connection=(HttpConnection)super.newConnection(channel,endpoint);
 
526
        ((HttpParser)connection.getParser()).setForceContentBuffer(true);
 
527
        return connection;
 
528
    }
 
529
 
 
530
    /* ------------------------------------------------------------ */
 
531
    protected SSLEngine createSSLEngine() throws IOException
 
532
    {
 
533
        SSLEngine engine=null;
 
534
        try
 
535
        {
 
536
            engine=_context.createSSLEngine();
 
537
            engine.setUseClientMode(false);
 
538
            
 
539
            if (_wantClientAuth)
 
540
                engine.setWantClientAuth(_wantClientAuth);
 
541
            if (_needClientAuth)
 
542
                engine.setNeedClientAuth(_needClientAuth);
 
543
            
 
544
            if (_excludeCipherSuites!=null&&_excludeCipherSuites.length>0)
 
545
            {
 
546
                List<String> excludedCSList=Arrays.asList(_excludeCipherSuites);
 
547
                String[] enabledCipherSuites=engine.getEnabledCipherSuites();
 
548
                List<String> enabledCSList=new ArrayList<String>(Arrays.asList(enabledCipherSuites));
 
549
 
 
550
                for (String cipherName : excludedCSList)
 
551
                {
 
552
                    if (enabledCSList.contains(cipherName))
 
553
                    {
 
554
                        enabledCSList.remove(cipherName);
 
555
                    }
 
556
                }
 
557
                enabledCipherSuites=enabledCSList.toArray(new String[enabledCSList.size()]);
 
558
 
 
559
                engine.setEnabledCipherSuites(enabledCipherSuites);
 
560
            }
 
561
 
 
562
        }
 
563
        catch (Exception e)
 
564
        {
 
565
            Log.warn("Error creating sslEngine -- closing this connector",e);
 
566
            close();
 
567
            throw new IllegalStateException(e);
 
568
        }
 
569
        return engine;
 
570
    }
 
571
 
 
572
   
 
573
    protected void doStart() throws Exception
 
574
    {
 
575
        _context=createSSLContext();
 
576
        
 
577
        SSLEngine engine=createSSLEngine();
 
578
        SSLSession ssl_session=engine.getSession();
 
579
        
 
580
        setHeaderBufferSize(ssl_session.getApplicationBufferSize());
 
581
        setRequestBufferSize(ssl_session.getApplicationBufferSize());
 
582
        setResponseBufferSize(ssl_session.getApplicationBufferSize());
 
583
        
 
584
        super.doStart();
 
585
    }
 
586
 
 
587
    protected SSLContext createSSLContext() throws Exception
 
588
    {
 
589
        if (_truststore==null)
 
590
        {
 
591
            _truststore=_keystore;
 
592
            _truststoreType=_keystoreType;
 
593
        }
 
594
 
 
595
        InputStream keystoreInputStream = null;
 
596
 
 
597
        KeyManager[] keyManagers=null;
 
598
        KeyStore keyStore = null;
 
599
        try
 
600
        {
 
601
            if (_keystore!=null)
 
602
            {
 
603
                keystoreInputStream=Resource.newResource(_keystore).getInputStream();
 
604
                keyStore = KeyStore.getInstance(_keystoreType);
 
605
                keyStore.load(keystoreInputStream,_password==null?null:_password.toString().toCharArray());
 
606
            }
 
607
        }
 
608
        finally
 
609
        {
 
610
            if (keystoreInputStream != null)
 
611
                keystoreInputStream.close();
 
612
        }
 
613
 
 
614
        KeyManagerFactory keyManagerFactory=KeyManagerFactory.getInstance(_sslKeyManagerFactoryAlgorithm);
 
615
        keyManagerFactory.init(keyStore,_keyPassword==null?(_password==null?null:_password.toString().toCharArray()):_keyPassword.toString().toCharArray());
 
616
        keyManagers=keyManagerFactory.getKeyManagers();
 
617
 
 
618
 
 
619
        TrustManager[] trustManagers=null;
 
620
        InputStream truststoreInputStream = null;
 
621
        KeyStore trustStore = null;
 
622
        try
 
623
        {
 
624
            if (_truststore!=null)
 
625
            {
 
626
                truststoreInputStream = Resource.newResource(_truststore).getInputStream();
 
627
                trustStore=KeyStore.getInstance(_truststoreType);
 
628
                trustStore.load(truststoreInputStream,_trustPassword==null?null:_trustPassword.toString().toCharArray());
 
629
            }
 
630
        }
 
631
        finally
 
632
        {
 
633
            if (truststoreInputStream != null)
 
634
                truststoreInputStream.close();
 
635
        }
 
636
 
 
637
 
 
638
        TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(_sslTrustManagerFactoryAlgorithm);
 
639
        trustManagerFactory.init(trustStore);
 
640
        trustManagers=trustManagerFactory.getTrustManagers();
 
641
 
 
642
        SecureRandom secureRandom=_secureRandomAlgorithm==null?null:SecureRandom.getInstance(_secureRandomAlgorithm);
 
643
        SSLContext context=_provider==null?SSLContext.getInstance(_protocol):SSLContext.getInstance(_protocol,_provider);
 
644
        context.init(keyManagers,trustManagers,secureRandom);
 
645
        return context;
 
646
    }
 
647
 
 
648
    /**
 
649
     * Simple bundle of information that is cached in the SSLSession. Stores the
 
650
     * effective keySize and the client certificate chain.
 
651
     */
 
652
    private class CachedInfo
 
653
    {
 
654
        private X509Certificate[] _certs;
 
655
        private Integer _keySize;
 
656
 
 
657
        CachedInfo(Integer keySize, X509Certificate[] certs)
 
658
        {
 
659
            this._keySize=keySize;
 
660
            this._certs=certs;
 
661
        }
 
662
 
 
663
        X509Certificate[] getCerts()
 
664
        {
 
665
            return _certs;
 
666
        }
 
667
 
 
668
        Integer getKeySize()
 
669
        {
 
670
            return _keySize;
 
671
        }
 
672
    }
 
673
 
 
674
}