summaryrefslogtreecommitdiffstats
blob: c3db11ab1bbe06efb1c73d653bd661880d678c9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*  Copyright (c) 2012, Isode Limited, London, England.
 *  All rights reserved.
 *
 *  Acquisition and use of this software and related materials for any
 *  purpose requires a written licence agreement from Isode Limited,
 *  or a written licence from an organisation licensed by Isode Limited Limited
 *  to grant such a licence.
 *
 */
 
package com.isode.stroke.tls.java;

import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 * A concrete X509TrustManager implementation which provides a trust manager 
 * based on the default java "pkcs12" keystore.
 */
public class JavaTrustManager implements X509TrustManager {
    
    /**
     * Construct a new object
     * @param jsseContext reference to JSSEContext; must not be null.
     * 
     * @throws SSLException if it was not possible to initialise the
     * TrustManager or KeyStore
     */
    JavaTrustManager(JSSEContext jsseContext) throws SSLException {

        if (jsseContext == null) {
            throw new NullPointerException("JSSEContext may not be null");
        }
        this.jsseContext = jsseContext;

        try {
            // create a "default" JSSE X509TrustManager.

            KeyStore ks = KeyStore.getInstance("PKCS12");
            /*

        // This is how you could load trust anchors
        ks.load(new FileInputStream("trustedCerts"),
            "passphrase".toCharArray());
             */
            TrustManagerFactory tmf =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(ks);

            TrustManager tms [] = tmf.getTrustManagers();

            /*
             * Iterate over the returned trustmanagers, look
             * for an instance of X509TrustManager.  If found,
             * use that as our "default" trust manager.
             */
            for (int i = 0; i < tms.length; i++) {
                if (tms[i] instanceof X509TrustManager) {
                    pkixTrustManager = (X509TrustManager) tms[i];                                      
                    return;
                }
            }
            /*
             * Find some other way to initialize, or else we have to fail the
             * constructor.
             */
            throw new SSLException("Couldn't initialize");
        }
        catch (KeyStoreException e) {
            throw new SSLException(e);
        }
        catch (NoSuchAlgorithmException e) {
            throw new SSLException(e);
        }
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // It's not expected that a Stroke application will ever be in the
        // position of checking client certificates.  Just delegate to
        // default trust manager
        pkixTrustManager.checkClientTrusted(chain, authType);

    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        CertificateException certificateException = null; 


        // TODO: 
        // Note that we don't call the superclass method here yet, because
        // it will fail with like this until the TrustManagerFactory has
        // been initialised with a suitable list of trust anchors
        // java.lang.RuntimeException: Unexpected error: 
        // java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
        
        /*
        try {
            pkixTrustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException e) {
            certificateException = e;
        }
        catch (Exception e) {
            emitError(e,"checkServerTrusted failed");
        }
        */
        
        // TODO: The only type of verification done is the certificate validity.
        // Need to make "checkServerTrusted" do certificate verification properly
        // and pass in an appropriate CertificateException
        if (chain != null && chain.length > 0) {
            try {
                chain[0].checkValidity();
            }
            catch (CertificateException e) {
                certificateException = e;
            }
        }

        jsseContext.setPeerCertificateInfo(chain, certificateException);
        
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }

    /*
     * The default PKIX X509TrustManager, to which decisions can be
     * delegated when we don't make them ourselves.
     */
    X509TrustManager pkixTrustManager;
    
    /**
     * The object who wants to know what server certificates appear 
     */
    JSSEContext jsseContext;
}