SSLSessionImpl.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.xnet.provider.jsse;
19
20import java.security.AccessControlContext;
21import java.security.AccessController;
22import java.security.Principal;
23import java.security.SecureRandom;
24import java.security.cert.Certificate;
25import java.security.cert.CertificateEncodingException;
26import java.security.cert.X509Certificate;
27import java.util.HashMap;
28import java.util.Map;
29import java.util.Vector;
30
31import javax.net.ssl.SSLPeerUnverifiedException;
32import javax.net.ssl.SSLPermission;
33import javax.net.ssl.SSLSession;
34import javax.net.ssl.SSLSessionBindingEvent;
35import javax.net.ssl.SSLSessionBindingListener;
36import javax.net.ssl.SSLSessionContext;
37
38/**
39 *
40 * SSLSession implementation
41 *
42 * @see javax.net.ssl.SSLSession
43 */
44public class SSLSessionImpl implements SSLSession, Cloneable  {
45
46    /**
47     * Session object reporting an invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
48     */
49    public static final SSLSessionImpl NULL_SESSION = new SSLSessionImpl(null);
50
51    /**
52     * Container class for the 'value' map's keys.
53     */
54    private static final class ValueKey {
55        final String name;
56        final AccessControlContext acc;
57
58        ValueKey(String name) {
59            super();
60            this.name = name;
61            this.acc = AccessController.getContext();
62        }
63
64        @Override
65        public int hashCode() {
66            final int prime = 31;
67            int result = 1;
68            result = prime * result + ((acc == null) ? 0 : acc.hashCode());
69            result = prime * result + ((name == null) ? 0 : name.hashCode());
70            return result;
71        }
72
73        @Override
74        public boolean equals(Object obj) {
75            if (this == obj)
76                return true;
77            if (obj == null)
78                return false;
79            if (!(obj instanceof ValueKey))
80                return false;
81            ValueKey other = (ValueKey) obj;
82            if (acc == null) {
83                if (other.acc != null)
84                    return false;
85            } else if (!acc.equals(other.acc))
86                return false;
87            if (name == null) {
88                if (other.name != null)
89                    return false;
90            } else if (!name.equals(other.name))
91                return false;
92            return true;
93        }
94    }
95
96    private long creationTime;
97    private boolean isValid = true;
98    private Map<ValueKey, Object> values = new HashMap<ValueKey, Object>();
99
100    /**
101     * ID of the session
102     */
103    byte[] id;
104
105    /**
106     * Last time the session was accessed
107     */
108    long lastAccessedTime;
109
110    /**
111     * Protocol used in the session
112     */
113    ProtocolVersion protocol;
114
115    /**
116     * CipherSuite used in the session
117     */
118    CipherSuite cipherSuite;
119
120    /**
121     * Context of the session
122     */
123// BEGIN android-changed
124    SSLSessionContext context;
125// END android-changed
126
127    /**
128     * certificates were sent to the peer
129     */
130    X509Certificate[] localCertificates;
131
132    /**
133     * Peer certificates
134     */
135    X509Certificate[] peerCertificates;
136
137    /**
138     * Peer host name
139     */
140    private String peerHost;
141
142    /**
143     * Peer port number
144     */
145    private int peerPort = -1;
146
147    /**
148     * Master secret
149     */
150    byte[] master_secret;
151
152    /**
153     * clientRandom
154     */
155    byte[] clientRandom;
156
157    /**
158     * serverRandom
159     */
160    byte[] serverRandom;
161
162    /**
163     * True if this entity is considered the server
164     */
165    final boolean isServer;
166
167    /**
168     * Creates SSLSession implementation
169     *
170     * @param cipher_suite
171     * @param sr
172     */
173    public SSLSessionImpl(CipherSuite cipher_suite, SecureRandom sr) {
174        creationTime = System.currentTimeMillis();
175        lastAccessedTime = creationTime;
176        if (cipher_suite == null) {
177            this.cipherSuite = CipherSuite.TLS_NULL_WITH_NULL_NULL;
178            id = new byte[0];
179            isServer = false;
180            isValid = false;
181        } else {
182            this.cipherSuite = cipher_suite;
183            id = new byte[32];
184            sr.nextBytes(id);
185            long time = creationTime / 1000;
186            id[28] = (byte) ((time & 0xFF000000) >>> 24);
187            id[29] = (byte) ((time & 0x00FF0000) >>> 16);
188            id[30] = (byte) ((time & 0x0000FF00) >>> 8);
189            id[31] = (byte) ((time & 0x000000FF));
190            isServer = true;
191        }
192
193    }
194
195    /**
196     * Creates SSLSession implementation
197     *
198     * @param sr
199     */
200    public SSLSessionImpl(SecureRandom sr) {
201        this(null, sr);
202    }
203
204    public int getApplicationBufferSize() {
205        return SSLRecordProtocol.MAX_DATA_LENGTH;
206    }
207
208    public String getCipherSuite() {
209        return cipherSuite.getName();
210    }
211
212    public long getCreationTime() {
213        return creationTime;
214    }
215
216    public byte[] getId() {
217        return id;
218    }
219
220    public long getLastAccessedTime() {
221        return lastAccessedTime;
222    }
223
224    public Certificate[] getLocalCertificates() {
225        return localCertificates;
226    }
227
228    public Principal getLocalPrincipal() {
229        if (localCertificates != null && localCertificates.length > 0) {
230            return localCertificates[0].getSubjectX500Principal();
231        }
232        return null;
233    }
234
235    public int getPacketBufferSize() {
236        return SSLRecordProtocol.MAX_SSL_PACKET_SIZE;
237    }
238
239    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
240            throws SSLPeerUnverifiedException {
241        if (peerCertificates == null) {
242            throw new SSLPeerUnverifiedException("No peer certificate");
243        }
244        javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[peerCertificates.length];
245        for (int i = 0; i < certs.length; i++) {
246            try {
247                certs[i] = javax.security.cert.X509Certificate.getInstance(peerCertificates[i]
248                        .getEncoded());
249            } catch (javax.security.cert.CertificateException e) {
250            } catch (CertificateEncodingException e) {
251            }
252        }
253        return certs;
254    }
255
256    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
257        if (peerCertificates == null) {
258            throw new SSLPeerUnverifiedException("No peer certificate");
259        }
260        return peerCertificates;
261    }
262
263    public String getPeerHost() {
264        return peerHost;
265    }
266
267    public int getPeerPort() {
268        return peerPort;
269    }
270
271    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
272        if (peerCertificates == null) {
273            throw new SSLPeerUnverifiedException("No peer certificate");
274        }
275        return peerCertificates[0].getSubjectX500Principal();
276    }
277
278    public String getProtocol() {
279        return (protocol == null) ? "NONE" : protocol.name;
280    }
281
282    public SSLSessionContext getSessionContext() {
283        SecurityManager sm = System.getSecurityManager();
284        if (sm != null) {
285            sm.checkPermission(new SSLPermission("getSSLSessionContext"));
286        }
287        return context;
288    }
289
290    public Object getValue(String name) {
291        if (name == null) {
292            throw new IllegalArgumentException("Parameter is null");
293        }
294        return values.get(new ValueKey(name));
295    }
296
297    public String[] getValueNames() {
298        final Vector<String> v = new Vector<String>();
299        final AccessControlContext currAcc = AccessController.getContext();
300        for (ValueKey key : values.keySet()) {
301            if ((currAcc == null && key.acc == null)
302                    || (currAcc != null && currAcc.equals(key.acc))) {
303                v.add(key.name);
304            }
305        }
306        return v.toArray(new String[v.size()]);
307    }
308
309    public void invalidate() {
310        isValid = false;
311        context = null;
312    }
313
314    public boolean isValid() {
315        if (isValid && context != null && context.getSessionTimeout() != 0
316                && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) {
317            isValid = false;
318        }
319        return isValid;
320    }
321
322    public void putValue(String name, Object value) {
323        if (name == null || value == null) {
324            throw new IllegalArgumentException("Parameter is null");
325        }
326        Object old = values.put(new ValueKey(name), value);
327        if (value instanceof SSLSessionBindingListener) {
328            ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
329        }
330        if (old instanceof SSLSessionBindingListener) {
331            ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
332        }
333
334    }
335
336    public void removeValue(String name) {
337        if (name == null) {
338            throw new IllegalArgumentException("Parameter is null");
339        }
340        Object old = values.remove(new ValueKey(name));
341        if (old instanceof SSLSessionBindingListener) {
342            SSLSessionBindingListener listener = (SSLSessionBindingListener) old;
343            listener.valueUnbound(new SSLSessionBindingEvent(this, name));
344        }
345    }
346
347    @Override
348    public Object clone() {
349        try {
350            return super.clone();
351        } catch (CloneNotSupportedException e) {
352            throw new AssertionError(e);
353        }
354    }
355
356    /**
357     * Sets the address of the peer
358     *
359     * @param peerHost
360     * @param peerPort
361     */
362    void setPeer(String peerHost, int peerPort) {
363        this.peerHost = peerHost;
364        this.peerPort = peerPort;
365    }
366}
367