1/*
2 * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.naming.ldap;
27
28import java.io.IOException;
29import javax.net.ssl.SSLSession;
30import javax.net.ssl.SSLSocketFactory;
31import javax.net.ssl.HostnameVerifier;
32
33/**
34 * This class implements the LDAPv3 Extended Response for StartTLS as
35 * defined in
36 * <a href="http://www.ietf.org/rfc/rfc2830.txt">Lightweight Directory
37 * Access Protocol (v3): Extension for Transport Layer Security</a>
38 *
39 * The object identifier for StartTLS is 1.3.6.1.4.1.1466.20037
40 * and no extended response value is defined.
41 *
42 *<p>
43 * The Start TLS extended request and response are used to establish
44 * a TLS connection over the existing LDAP connection associated with
45 * the JNDI context on which {@code extendedOperation()} is invoked.
46 * Typically, a JNDI program uses the StartTLS extended request and response
47 * classes as follows.
48 * <blockquote><pre>
49 * import javax.naming.ldap.*;
50 *
51 * // Open an LDAP association
52 * LdapContext ctx = new InitialLdapContext();
53 *
54 * // Perform a StartTLS extended operation
55 * StartTlsResponse tls =
56 *     (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
57 *
58 * // Open a TLS connection (over the existing LDAP association) and get details
59 * // of the negotiated TLS session: cipher suite, peer certificate, ...
60 * SSLSession session = tls.negotiate();
61 *
62 * // ... use ctx to perform protected LDAP operations
63 *
64 * // Close the TLS connection (revert back to the underlying LDAP association)
65 * tls.close();
66 *
67 * // ... use ctx to perform unprotected LDAP operations
68 *
69 * // Close the LDAP association
70 * ctx.close;
71 * </pre></blockquote>
72 *
73 * @since 1.4
74 * @see StartTlsRequest
75 * @author Vincent Ryan
76 */
77public abstract class StartTlsResponse implements ExtendedResponse {
78
79    // Constant
80
81    /**
82     * The StartTLS extended response's assigned object identifier
83     * is 1.3.6.1.4.1.1466.20037.
84     */
85    public static final String OID = "1.3.6.1.4.1.1466.20037";
86
87
88    // Called by subclass
89
90    /**
91     * Constructs a StartTLS extended response.
92     * A concrete subclass must have a public no-arg constructor.
93     */
94    protected StartTlsResponse() {
95    }
96
97
98    // ExtendedResponse methods
99
100    /**
101     * Retrieves the StartTLS response's object identifier string.
102     *
103     * @return The object identifier string, "1.3.6.1.4.1.1466.20037".
104     */
105    public String getID() {
106        return OID;
107    }
108
109    /**
110     * Retrieves the StartTLS response's ASN.1 BER encoded value.
111     * Since the response has no defined value, null is always
112     * returned.
113     *
114     * @return The null value.
115     */
116    public byte[] getEncodedValue() {
117        return null;
118    }
119
120    // StartTls-specific methods
121
122    /**
123     * Overrides the default list of cipher suites enabled for use on the
124     * TLS connection. The cipher suites must have already been listed by
125     * {@code SSLSocketFactory.getSupportedCipherSuites()} as being supported.
126     * Even if a suite has been enabled, it still might not be used because
127     * the peer does not support it, or because the requisite certificates
128     * (and private keys) are not available.
129     *
130     * @param suites The non-null list of names of all the cipher suites to
131     * enable.
132     * @see #negotiate
133     */
134    public abstract void setEnabledCipherSuites(String[] suites);
135
136    /**
137     * Sets the hostname verifier used by {@code negotiate()}
138     * after the TLS handshake has completed and the default hostname
139     * verification has failed.
140     * {@code setHostnameVerifier()} must be called before
141     * {@code negotiate()} is invoked for it to have effect.
142     * If called after
143     * {@code negotiate()}, this method does not do anything.
144     *
145     * @param verifier The non-null hostname verifier callback.
146     * @see #negotiate
147     */
148    public abstract void setHostnameVerifier(HostnameVerifier verifier);
149
150    /**
151     * Negotiates a TLS session using the default SSL socket factory.
152     * <p>
153     * This method is equivalent to {@code negotiate(null)}.
154     *
155     * @return The negotiated SSL session
156     * @throws IOException If an IO error was encountered while establishing
157     * the TLS session.
158     * @see #setEnabledCipherSuites
159     * @see #setHostnameVerifier
160     */
161    public abstract SSLSession negotiate() throws IOException;
162
163    /**
164     * Negotiates a TLS session using an SSL socket factory.
165     * <p>
166     * Creates an SSL socket using the supplied SSL socket factory and
167     * attaches it to the existing connection. Performs the TLS handshake
168     * and returns the negotiated session information.
169     * <p>
170     * If cipher suites have been set via {@code setEnabledCipherSuites}
171     * then they are enabled before the TLS handshake begins.
172     * <p>
173     * Hostname verification is performed after the TLS handshake completes.
174     * The default hostname verification performs a match of the server's
175     * hostname against the hostname information found in the server's certificate.
176     * If this verification fails and no callback has been set via
177     * {@code setHostnameVerifier} then the negotiation fails.
178     * If this verification fails and a callback has been set via
179     * {@code setHostnameVerifier}, then the callback is used to determine whether
180     * the negotiation succeeds.
181     * <p>
182     * If an error occurs then the SSL socket is closed and an IOException
183     * is thrown. The underlying connection remains intact.
184     *
185     * @param factory The possibly null SSL socket factory to use.
186     * If null, the default SSL socket factory is used.
187     * @return The negotiated SSL session
188     * @throws IOException If an IO error was encountered while establishing
189     * the TLS session.
190     * @see #setEnabledCipherSuites
191     * @see #setHostnameVerifier
192     */
193    public abstract SSLSession negotiate(SSLSocketFactory factory)
194        throws IOException;
195
196    /**
197     * Closes the TLS connection gracefully and reverts back to the underlying
198     * connection.
199     *
200     * @throws IOException If an IO error was encountered while closing the
201     * TLS connection
202     */
203    public abstract void close() throws IOException;
204
205    private static final long serialVersionUID = 8372842182579276418L;
206}
207