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.conscrypt;
19
20import java.security.Principal;
21import java.security.cert.Certificate;
22import java.util.HashMap;
23import javax.net.ssl.*;
24
25/**
26 * This is returned in the place of a {@link SSLSession} when no TLS connection could be negotiated,
27 * but one was requested from a method that can't throw an exception such as {@link
28 * SSLSocket#getSession()} before {@link SSLSocket#startHandshake()} is called.
29 *
30 * @hide
31 */
32@Internal
33public final class SSLNullSession implements SSLSession, Cloneable {
34
35    /*
36     * Holds default instances so class preloading doesn't create an instance of
37     * it.
38     */
39    private static class DefaultHolder {
40        public static final SSLNullSession NULL_SESSION = new SSLNullSession();
41    }
42
43    private final HashMap<String, Object> values = new HashMap<String, Object>();
44
45    long creationTime;
46    long lastAccessedTime;
47
48    public static SSLSession getNullSession() {
49        return DefaultHolder.NULL_SESSION;
50    }
51
52    public SSLNullSession() {
53        creationTime = System.currentTimeMillis();
54        lastAccessedTime = creationTime;
55    }
56
57    @Override
58    public int getApplicationBufferSize() {
59        return NativeConstants.SSL3_RT_MAX_PLAIN_LENGTH;
60    }
61
62    @Override
63    public String getCipherSuite() {
64        return "SSL_NULL_WITH_NULL_NULL";
65    }
66
67    @Override
68    public long getCreationTime() {
69        return creationTime;
70    }
71
72    @Override
73    public byte[] getId() {
74        return EmptyArray.BYTE;
75    }
76
77    @Override
78    public long getLastAccessedTime() {
79        return lastAccessedTime;
80    }
81
82    @Override
83    public Certificate[] getLocalCertificates() {
84        return null;
85    }
86
87    @Override
88    public Principal getLocalPrincipal() {
89        return null;
90    }
91
92    @Override
93    public int getPacketBufferSize() {
94        return NativeConstants.SSL3_RT_MAX_PACKET_SIZE;
95    }
96
97    @Override
98    public javax.security.cert.X509Certificate[] getPeerCertificateChain()
99            throws SSLPeerUnverifiedException {
100        throw new SSLPeerUnverifiedException("No peer certificate");
101    }
102
103    @Override
104    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
105        throw new SSLPeerUnverifiedException("No peer certificate");
106    }
107
108    @Override
109    public String getPeerHost() {
110        return null;
111    }
112
113    @Override
114    public int getPeerPort() {
115        return -1;
116    }
117
118    @Override
119    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
120        throw new SSLPeerUnverifiedException("No peer certificate");
121    }
122
123    @Override
124    public String getProtocol() {
125        return "NONE";
126    }
127
128    @Override
129    public SSLSessionContext getSessionContext() {
130        return null;
131    }
132
133    @Override
134    public Object getValue(String name) {
135        if (name == null) {
136            throw new IllegalArgumentException("name == null");
137        }
138        return values.get(name);
139    }
140
141    @Override
142    public String[] getValueNames() {
143        return values.keySet().toArray(new String[values.size()]);
144    }
145
146    @Override
147    public void invalidate() {
148    }
149
150    @Override
151    public boolean isValid() {
152        return false;
153    }
154
155    @Override
156    public void putValue(String name, Object value) {
157        if (name == null || value == null) {
158            throw new IllegalArgumentException("name == null || value == null");
159        }
160        Object old = values.put(name, value);
161        if (value instanceof SSLSessionBindingListener) {
162            ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
163        }
164        if (old instanceof SSLSessionBindingListener) {
165            ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
166        }
167
168    }
169
170    @Override
171    public void removeValue(String name) {
172        if (name == null) {
173            throw new IllegalArgumentException("name == null");
174        }
175        Object old = values.remove(name);
176        if (old instanceof SSLSessionBindingListener) {
177            SSLSessionBindingListener listener = (SSLSessionBindingListener) old;
178            listener.valueUnbound(new SSLSessionBindingEvent(this, name));
179        }
180    }
181}
182