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 javax.net.ssl;
19
20import java.nio.ByteBuffer;
21
22/**
23 * The abstract implementation of secure communications using SSL, TLS, or other
24 * protocols. It includes the setup, handshake, and encrypt/decrypt
25 * functionality needed to create a secure connection.
26 *
27 * @since 1.5
28 */
29public abstract class SSLEngine {
30    private final String peerHost;
31    private final int peerPort;
32
33    /**
34     * Creates a new {@code SSLEngine} instance.
35     */
36    protected SSLEngine() {
37        peerHost = null;
38        peerPort = -1;
39    }
40
41    /**
42     * Creates a new {@code SSLEngine} instance with the specified host and
43     * port.
44     *
45     * @param host
46     *            the name of the host.
47     * @param port
48     *            the port of the host.
49     */
50    protected SSLEngine(String host, int port) {
51        this.peerHost = host;
52        this.peerPort = port;
53    }
54
55    /**
56     * Returns the name of the peer host.
57     *
58     * @return the name of the peer host, or {@code null} if none is available.
59     */
60    public String getPeerHost() {
61        return peerHost;
62    }
63
64    /**
65     * Returns the port number of the peer host.
66     *
67     * @return the port number of the peer host, or {@code -1} is none is
68     *         available.
69     */
70    public int getPeerPort() {
71        return peerPort;
72    }
73
74    /**
75     * Initiates a handshake on this engine.
76     * <p>
77     * Calling this method is not needed for the initial handshake: it will be
78     * called by {@code wrap} or {@code unwrap} if the initial handshake has not
79     * been started yet.
80     *
81     * @throws SSLException
82     *             if starting the handshake fails.
83     * @throws IllegalStateException
84     *             if the engine does not have all the needed settings (e.g.
85     *             client/server mode not set).
86     */
87    public abstract void beginHandshake() throws SSLException;
88
89    /**
90     * Notifies this engine instance that no more inbound network data will be
91     * sent to this engine.
92     *
93     * @throws SSLException
94     *             if this engine did not receive a needed protocol specific
95     *             close notification message from the peer.
96     */
97    public abstract void closeInbound() throws SSLException;
98
99    /**
100     * Notifies this engine instance that no more outbound application data will
101     * be sent to this engine.
102     */
103    public abstract void closeOutbound();
104
105    /**
106     * Returns a delegate task for this engine instance. Some engine operations
107     * may require the results of blocking or long running operations, and the
108     * {@code SSLEngineResult} instances returned by this engine may indicate
109     * that a delegated task result is needed. In this case the
110     * {@link Runnable#run() run} method of the returned {@code Runnable}
111     * delegated task must be called.
112     *
113     * @return a delegate task, or {@code null} if none are available.
114     */
115    public abstract Runnable getDelegatedTask();
116
117    /**
118     * Returns the SSL cipher suite names that are enabled in this engine
119     * instance.
120     *
121     * @return the SSL cipher suite names that are enabled in this engine
122     *         instance.
123     */
124    public abstract String[] getEnabledCipherSuites();
125
126    /**
127     * Returns the protocol version names that are enabled in this engine
128     * instance.
129     *
130     * @return the protocol version names that are enabled in this engine
131     *         instance.
132     */
133    public abstract String[] getEnabledProtocols();
134
135    /**
136     * Returns whether new SSL sessions may be established by this engine.
137     *
138     * @return {@code true} if new session may be established, {@code false} if
139     *         existing sessions must be reused.
140     */
141    public abstract boolean getEnableSessionCreation();
142
143    /**
144     * Returns the status of the handshake of this engine instance.
145     *
146     * @return the status of the handshake of this engine instance.
147     */
148    public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus();
149
150    /**
151     * Returns whether this engine instance will require client authentication.
152     *
153     * @return {@code true} if this engine will require client authentication,
154     *         {@code false} if no client authentication is needed.
155     */
156    public abstract boolean getNeedClientAuth();
157
158    /**
159     * Returns the SSL session for this engine instance.
160     *
161     * @return the SSL session for this engine instance.
162     */
163    public abstract SSLSession getSession();
164
165    /**
166     * Returns the SSL cipher suite names that are supported by this engine.
167     * These cipher suites can be enabled using
168     * {@link #setEnabledCipherSuites(String[])}.
169     *
170     * @return the SSL cipher suite names that are supported by this engine.
171     */
172    public abstract String[] getSupportedCipherSuites();
173
174    /**
175     * Returns the protocol names that are supported by this engine. These
176     * protocols can be enables using {@link #setEnabledProtocols(String[])}.
177     *
178     * @return the protocol names that are supported by this engine.
179     */
180    public abstract String[] getSupportedProtocols();
181
182    /**
183     * Returns whether this engine is set to act in client mode when
184     * handshaking.
185     *
186     * @return {@code true} if the engine is set to do handshaking in client
187     *         mode.
188     */
189    public abstract boolean getUseClientMode();
190
191    /**
192     * Returns whether this engine will request client authentication.
193     *
194     * @return {@code true} if client authentication will be requested,
195     *         {@code false} otherwise.
196     */
197    public abstract boolean getWantClientAuth();
198
199    /**
200     * Returns whether no more inbound data will be accepted by this engine.
201     *
202     * @return {@code true} if no more inbound data will be accepted by this
203     *         engine, {@code false} otherwise.
204     */
205    public abstract boolean isInboundDone();
206
207    /**
208     * Returns whether no more outbound data will be produced by this engine.
209     *
210     * @return {@code true} if no more outbound data will be producted by this
211     *         engine, {@code otherwise} false.
212     */
213    public abstract boolean isOutboundDone();
214
215    /**
216     * Sets the SSL cipher suite names that should be enabled in this engine
217     * instance. Only cipher suites listed by {@code getSupportedCipherSuites()}
218     * are allowed.
219     *
220     * @param suites
221     *            the SSL cipher suite names to be enabled.
222     * @throws IllegalArgumentException
223     *             if one of the specified cipher suites is not supported, or if
224     *             {@code suites} is {@code null}.
225     */
226    public abstract void setEnabledCipherSuites(String[] suites);
227
228    /**
229     * Sets the protocol version names that should be enabled in this engine
230     * instance. Only protocols listed by {@code getSupportedProtocols()} are
231     * allowed.
232     *
233     * @param protocols
234     *            the protocol version names to be enabled.
235     * @throws IllegalArgumentException
236     *             if one of the protocol version names is not supported, or if
237     *             {@code protocols} is {@code null}.
238     */
239    public abstract void setEnabledProtocols(String[] protocols);
240
241    /**
242     * Sets whether new SSL sessions may be established by this engine instance.
243     *
244     * @param flag
245     *            {@code true} if new SSL sessions may be established,
246     *            {@code false} if existing SSL sessions must be reused.
247     */
248    public abstract void setEnableSessionCreation(boolean flag);
249
250    /**
251     * Sets whether this engine must require client authentication. The client
252     * authentication is one of:
253     * <ul>
254     * <li>authentication required</li>
255     * <li>authentication requested</li>
256     * <li>no authentication needed</li>
257     * </ul>
258     * This method overrides the setting of {@link #setWantClientAuth(boolean)}.
259     *
260     * @param need
261     *            {@code true} if client authentication is required,
262     *            {@code false} if no authentication is needed.
263     */
264    public abstract void setNeedClientAuth(boolean need);
265
266    /**
267     * Sets whether this engine should act in client (or server) mode when
268     * handshaking.
269     *
270     * @param mode
271     *            {@code true} if this engine should act in client mode,
272     *            {@code false} if not.
273     * @throws IllegalArgumentException
274     *             if this method is called after starting the initial
275     *             handshake.
276     */
277    public abstract void setUseClientMode(boolean mode);
278
279    /**
280     * Sets whether this engine should request client authentication. The client
281     * authentication is one of the following:
282     * <ul>
283     * <li>authentication required</li>
284     * <li>authentication requested</li>
285     * <li>no authentication needed</li>
286     * </ul>
287     * This method overrides the setting of {@link #setNeedClientAuth(boolean)}.
288     *
289     * @param want
290     *            {@code true} if client authentication should be requested,
291     *            {@code false} if no authentication is needed.
292     */
293    public abstract void setWantClientAuth(boolean want);
294
295    /**
296     * Decodes the incoming network data buffer into application data buffers.
297     * If a handshake has not been started yet, it will automatically be
298     * started.
299     *
300     * @param src
301     *            the buffer with incoming network data
302     * @param dsts
303     *            the array of destination buffers for incoming application
304     *            data.
305     * @param offset
306     *            the offset in the array of destination buffers to which data
307     *            is to be transferred.
308     * @param length
309     *            the maximum number of destination buffers to be used.
310     * @return the result object of this operation.
311     * @throws SSLException
312     *             if a problem occurred while processing the data.
313     * @throws IndexOutOfBoundsException
314     *             if {@code length} is greater than
315     *             {@code dsts.length - offset}.
316     * @throws java.nio.ReadOnlyBufferException
317     *             if one of the destination buffers is read-only.
318     * @throws IllegalArgumentException
319     *             if {@code src}, {@code dsts}, or one of the entries in
320     *             {@code dsts} is {@code null}.
321     * @throws IllegalStateException
322     *             if the engine does not have all the needed settings (e.g.
323     *             client/server mode not set).
324     */
325    public abstract SSLEngineResult unwrap(ByteBuffer src,
326                                           ByteBuffer[] dsts,
327                                           int offset,
328                                           int length) throws SSLException;
329
330    /**
331     * Encodes the outgoing application data buffers into the network data
332     * buffer. If a handshake has not been started yet, it will automatically be
333     * started.
334     *
335     * @param srcs
336     *            the array of source buffers of outgoing application data.
337     * @param offset
338     *            the offset in the array of source buffers from which data is
339     *            to be retrieved.
340     * @param length
341     *            the maximum number of source buffers to be used.
342     * @param dst
343     *            the destination buffer for network data.
344     * @return the result object of this operation.
345     * @throws SSLException
346     *             if a problem occurred while processing the data.
347     * @throws IndexOutOfBoundsException
348     *             if {@code length} is greater than
349     *             {@code srcs.length - offset}.
350     * @throws java.nio.ReadOnlyBufferException
351     *             if the destination buffer is readonly.
352     * @throws IllegalArgumentException
353     *             if {@code srcs}, {@code dst}, or one the entries in
354     *             {@code srcs} is {@code null}.
355     * @throws IllegalStateException
356     *             if the engine does not have all the needed settings (e.g.
357     *             client/server mode not set).
358     */
359    public abstract SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
360            throws SSLException;
361
362    /**
363     * Decodes the incoming network data buffer into the application data
364     * buffer. If a handshake has not been started yet, it will automatically be
365     * started.
366     *
367     * @param src
368     *            the buffer with incoming network data
369     * @param dst
370     *            the destination buffer for incoming application data.
371     * @return the result object of this operation.
372     * @throws SSLException
373     *             if a problem occurred while processing the data.
374     * @throws java.nio.ReadOnlyBufferException
375     *             if one of the destination buffers is read-only.
376     * @throws IllegalArgumentException
377     *             if {@code src} or {@code dst} is {@code null}.
378     * @throws IllegalStateException
379     *             if the engine does not have all the needed settings (e.g.
380     *             client/server mode not set).
381     */
382    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
383        return unwrap(src, new ByteBuffer[] { dst }, 0, 1);
384    }
385
386    /**
387     * Decodes the incoming network data buffer into the application data
388     * buffers. If a handshake has not been started yet, it will automatically
389     * be started.
390     *
391     * @param src
392     *            the buffer with incoming network data
393     * @param dsts
394     *            the array of destination buffers for incoming application
395     *            data.
396     * @return the result object of this operation.
397     * @throws SSLException
398     *             if a problem occurred while processing the data.
399     * @throws java.nio.ReadOnlyBufferException
400     *             if one of the destination buffers is read-only.
401     * @throws IllegalArgumentException
402     *             if {@code src} or {@code dsts} is {@code null}.
403     * @throws IllegalStateException
404     *             if the engine does not have all the needed settings (e.g.
405     *             client/server mode not set).
406     */
407    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
408        if (dsts == null) {
409            throw new IllegalArgumentException("Byte buffer array dsts is null");
410        }
411        return unwrap(src, dsts, 0, dsts.length);
412    }
413
414    /**
415     * Encodes the outgoing application data buffers into the network data
416     * buffer. If a handshake has not been started yet, it will automatically be
417     * started.
418     *
419     * @param srcs
420     *            the array of source buffers of outgoing application data.
421     * @param dst
422     *            the destination buffer for network data.
423     * @return the result object of this operation.
424     * @throws SSLException
425     *             if a problem occurred while processing the data.
426     * @throws java.nio.ReadOnlyBufferException
427     *             if the destination buffer is readonly.
428     * @throws IllegalArgumentException
429     *             if {@code srcs} or {@code dst} is {@code null}.
430     * @throws IllegalStateException
431     *             if the engine does not have all the needed settings (e.g.
432     *             client/server mode not set).
433     */
434    public SSLEngineResult wrap(ByteBuffer[] srcs, ByteBuffer dst) throws SSLException {
435        if (srcs == null) {
436            throw new IllegalArgumentException("Byte buffer array srcs is null");
437        }
438        return wrap(srcs, 0, srcs.length, dst);
439    }
440
441    /**
442     * Encodes the outgoing application data buffer into the network data
443     * buffer. If a handshake has not been started yet, it will automatically be
444     * started.
445     *
446     * @param src
447     *            the source buffers of outgoing application data.
448     * @param dst
449     *            the destination buffer for network data.
450     * @return the result object of this operation.
451     * @throws SSLException
452     *             if a problem occurred while processing the data.
453     * @throws java.nio.ReadOnlyBufferException
454     *             if the destination buffer is readonly.
455     * @throws IllegalArgumentException
456     *             if {@code src} or {@code dst} is {@code null}.
457     * @throws IllegalStateException
458     *             if the engine does not have all the needed settings (e.g.
459     *             client/server mode not set).
460     */
461    public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
462        return wrap(new ByteBuffer[] { src }, 0, 1, dst);
463    }
464
465    /**
466     * Returns a new SSLParameters based on this SSLSocket's current
467     * cipher suites, protocols, and client authentication settings.
468     *
469     * @since 1.6
470     */
471    public SSLParameters getSSLParameters() {
472        SSLParameters p = new SSLParameters();
473        p.setCipherSuites(getEnabledCipherSuites());
474        p.setProtocols(getEnabledProtocols());
475        p.setNeedClientAuth(getNeedClientAuth());
476        p.setWantClientAuth(getWantClientAuth());
477        return p;
478    }
479
480    /**
481     * Sets various SSL handshake parameters based on the SSLParameter
482     * argument. Specifically, sets the SSLEngine's enabled cipher
483     * suites if the parameter's cipher suites are non-null. Similarly
484     * sets the enabled protocols. If the parameters specify the want
485     * or need for client authentication, those requirements are set
486     * on the SSLEngine, otherwise both are set to false.
487     * @since 1.6
488     */
489    public void setSSLParameters(SSLParameters p) {
490        String[] cipherSuites = p.getCipherSuites();
491        if (cipherSuites != null) {
492            setEnabledCipherSuites(cipherSuites);
493        }
494        String[] protocols = p.getProtocols();
495        if (protocols != null) {
496            setEnabledProtocols(protocols);
497        }
498        if (p.getNeedClientAuth()) {
499            setNeedClientAuth(true);
500        } else if (p.getWantClientAuth()) {
501            setWantClientAuth(true);
502        } else {
503            setWantClientAuth(false);
504        }
505    }
506}
507