SSLSessionImpl.java revision 32c2297a959b72abdb18743f0519e1d8b7c7ea88
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.ArrayList;
28import java.util.HashMap;
29import java.util.Map;
30import javax.net.ssl.SSLPeerUnverifiedException;
31import javax.net.ssl.SSLPermission;
32import javax.net.ssl.SSLSession;
33import javax.net.ssl.SSLSessionBindingEvent;
34import javax.net.ssl.SSLSessionBindingListener;
35import javax.net.ssl.SSLSessionContext;
36import libcore.util.EmptyArray;
37import libcore.util.Objects;
38
39/**
40 *
41 * SSLSession implementation
42 *
43 * @see javax.net.ssl.SSLSession
44 */
45public class SSLSessionImpl implements SSLSession, Cloneable  {
46
47    /**
48     * Session object reporting an invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
49     */
50    public static final SSLSessionImpl NULL_SESSION = new SSLSessionImpl(null);
51
52    /**
53     * Container class for the 'value' map's keys.
54     */
55    private static final class ValueKey {
56        final String name;
57        final AccessControlContext acc;
58
59        ValueKey(String name) {
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    SSLSessionContext context;
124
125    /**
126     * certificates were sent to the peer
127     */
128    X509Certificate[] localCertificates;
129
130    /**
131     * Peer certificates
132     */
133    X509Certificate[] peerCertificates;
134
135    /**
136     * Peer host name
137     */
138    private String peerHost;
139
140    /**
141     * Peer port number
142     */
143    private int peerPort = -1;
144
145    /**
146     * Master secret
147     */
148    byte[] master_secret;
149
150    /**
151     * clientRandom
152     */
153    byte[] clientRandom;
154
155    /**
156     * serverRandom
157     */
158    byte[] serverRandom;
159
160    /**
161     * True if this entity is considered the server
162     */
163    final boolean isServer;
164
165    /**
166     * Creates SSLSession implementation
167     *
168     * @param cipher_suite
169     * @param sr
170     */
171    public SSLSessionImpl(CipherSuite cipher_suite, SecureRandom sr) {
172        creationTime = System.currentTimeMillis();
173        lastAccessedTime = creationTime;
174        if (cipher_suite == null) {
175            this.cipherSuite = CipherSuite.SSL_NULL_WITH_NULL_NULL;
176            id = EmptyArray.BYTE;
177            isServer = false;
178            isValid = false;
179        } else {
180            this.cipherSuite = cipher_suite;
181            id = new byte[32];
182            sr.nextBytes(id);
183            long time = creationTime / 1000;
184            id[28] = (byte) ((time & 0xFF000000) >>> 24);
185            id[29] = (byte) ((time & 0x00FF0000) >>> 16);
186            id[30] = (byte) ((time & 0x0000FF00) >>> 8);
187            id[31] = (byte) ((time & 0x000000FF));
188            isServer = true;
189        }
190
191    }
192
193    /**
194     * Creates SSLSession implementation
195     *
196     * @param sr
197     */
198    public SSLSessionImpl(SecureRandom sr) {
199        this(null, sr);
200    }
201
202    public int getApplicationBufferSize() {
203        return SSLRecordProtocol.MAX_DATA_LENGTH;
204    }
205
206    public String getCipherSuite() {
207        return cipherSuite.getName();
208    }
209
210    public long getCreationTime() {
211        return creationTime;
212    }
213
214    public byte[] getId() {
215        return id;
216    }
217
218    public long getLastAccessedTime() {
219        return lastAccessedTime;
220    }
221
222    public Certificate[] getLocalCertificates() {
223        return localCertificates;
224    }
225
226    public Principal getLocalPrincipal() {
227        if (localCertificates != null && localCertificates.length > 0) {
228            return localCertificates[0].getSubjectX500Principal();
229        }
230        return null;
231    }
232
233    public int getPacketBufferSize() {
234        return SSLRecordProtocol.MAX_SSL_PACKET_SIZE;
235    }
236
237    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
238            throws SSLPeerUnverifiedException {
239        if (peerCertificates == null) {
240            throw new SSLPeerUnverifiedException("No peer certificate");
241        }
242        javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[peerCertificates.length];
243        for (int i = 0; i < certs.length; i++) {
244            try {
245                certs[i] = javax.security.cert.X509Certificate.getInstance(peerCertificates[i]
246                        .getEncoded());
247            } catch (javax.security.cert.CertificateException e) {
248            } catch (CertificateEncodingException e) {
249            }
250        }
251        return certs;
252    }
253
254    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
255        if (peerCertificates == null) {
256            throw new SSLPeerUnverifiedException("No peer certificate");
257        }
258        return peerCertificates;
259    }
260
261    public String getPeerHost() {
262        return peerHost;
263    }
264
265    public int getPeerPort() {
266        return peerPort;
267    }
268
269    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
270        if (peerCertificates == null) {
271            throw new SSLPeerUnverifiedException("No peer certificate");
272        }
273        return peerCertificates[0].getSubjectX500Principal();
274    }
275
276    public String getProtocol() {
277        return (protocol == null) ? "NONE" : protocol.name;
278    }
279
280    public SSLSessionContext getSessionContext() {
281        return context;
282    }
283
284    public Object getValue(String name) {
285        if (name == null) {
286            throw new IllegalArgumentException("Parameter is null");
287        }
288        return values.get(new ValueKey(name));
289    }
290
291    public String[] getValueNames() {
292        final ArrayList<String> v = new ArrayList<String>();
293        final AccessControlContext currAcc = AccessController.getContext();
294        for (ValueKey key : values.keySet()) {
295            if (Objects.equal(currAcc, key.acc)) {
296                v.add(key.name);
297            }
298        }
299        return v.toArray(new String[v.size()]);
300    }
301
302    public void invalidate() {
303        isValid = false;
304        context = null;
305    }
306
307    public boolean isValid() {
308        if (isValid && context != null && context.getSessionTimeout() != 0
309                && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) {
310            isValid = false;
311        }
312        return isValid;
313    }
314
315    public void putValue(String name, Object value) {
316        if (name == null || value == null) {
317            throw new IllegalArgumentException("Parameter is null");
318        }
319        Object old = values.put(new ValueKey(name), value);
320        if (value instanceof SSLSessionBindingListener) {
321            ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
322        }
323        if (old instanceof SSLSessionBindingListener) {
324            ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
325        }
326
327    }
328
329    public void removeValue(String name) {
330        if (name == null) {
331            throw new IllegalArgumentException("Parameter is null");
332        }
333        Object old = values.remove(new ValueKey(name));
334        if (old instanceof SSLSessionBindingListener) {
335            SSLSessionBindingListener listener = (SSLSessionBindingListener) old;
336            listener.valueUnbound(new SSLSessionBindingEvent(this, name));
337        }
338    }
339
340    @Override
341    public Object clone() {
342        try {
343            return super.clone();
344        } catch (CloneNotSupportedException e) {
345            throw new AssertionError(e);
346        }
347    }
348
349    /**
350     * Sets the address of the peer
351     *
352     * @param peerHost
353     * @param peerPort
354     */
355    void setPeer(String peerHost, int peerPort) {
356        this.peerHost = peerHost;
357        this.peerPort = peerPort;
358    }
359}
360