Path: blob/master/src/java.security.sasl/share/classes/javax/security/sasl/SaslClient.java
41159 views
/*1* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.security.sasl;2627/**28* Performs SASL authentication as a client.29* <p>30* A protocol library such as one for LDAP gets an instance of this31* class in order to perform authentication defined by a specific SASL32* mechanism. Invoking methods on the {@code SaslClient} instance33* process challenges and create responses according to the SASL34* mechanism implemented by the {@code SaslClient}.35* As the authentication proceeds, the instance36* encapsulates the state of a SASL client's authentication exchange.37* <p>38* Here's an example of how an LDAP library might use a {@code SaslClient}.39* It first gets an instance of a {@code SaslClient}:40* <blockquote><pre>{@code41* SaslClient sc = Sasl.createSaslClient(mechanisms,42* authorizationId, protocol, serverName, props, callbackHandler);43* }</pre></blockquote>44* It can then proceed to use the client for authentication.45* For example, an LDAP library might use the client as follows:46* <blockquote><pre>{@code47* // Get initial response and send to server48* byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[0]) :49* null);50* LdapResult res = ldap.sendBindRequest(dn, sc.getName(), response);51* while (!sc.isComplete() &&52* (res.status == SASL_BIND_IN_PROGRESS || res.status == SUCCESS)) {53* response = sc.evaluateChallenge(res.getBytes());54* if (res.status == SUCCESS) {55* // we're done; don't expect to send another BIND56* if (response != null) {57* throw new SaslException(58* "Protocol error: attempting to send response after completion");59* }60* break;61* }62* res = ldap.sendBindRequest(dn, sc.getName(), response);63* }64* if (sc.isComplete() && res.status == SUCCESS) {65* String qop = (String) sc.getNegotiatedProperty(Sasl.QOP);66* if (qop != null67* && (qop.equalsIgnoreCase("auth-int")68* || qop.equalsIgnoreCase("auth-conf"))) {69*70* // Use SaslClient.wrap() and SaslClient.unwrap() for future71* // communication with server72* ldap.in = new SecureInputStream(sc, ldap.in);73* ldap.out = new SecureOutputStream(sc, ldap.out);74* }75* }76* }</pre></blockquote>77*78* If the mechanism has an initial response, the library invokes79* {@code evaluateChallenge()} with an empty80* challenge and to get initial response.81* Protocols such as IMAP4, which do not include an initial response with82* their first authentication command to the server, initiates the83* authentication without first calling {@code hasInitialResponse()}84* or {@code evaluateChallenge()}.85* When the server responds to the command, it sends an initial challenge.86* For a SASL mechanism in which the client sends data first, the server should87* have issued a challenge with no data. This will then result in a call88* (on the client) to {@code evaluateChallenge()} with an empty challenge.89*90* @since 1.591*92* @see Sasl93* @see SaslClientFactory94*95* @author Rosanna Lee96* @author Rob Weltman97*/98public abstract interface SaslClient {99100/**101* Returns the IANA-registered mechanism name of this SASL client.102* (e.g. "CRAM-MD5", "GSSAPI").103* @return A non-null string representing the IANA-registered mechanism name.104*/105public abstract String getMechanismName();106107/**108* Determines whether this mechanism has an optional initial response.109* If true, caller should call {@code evaluateChallenge()} with an110* empty array to get the initial response.111*112* @return true if this mechanism has an initial response.113*/114public abstract boolean hasInitialResponse();115116/**117* Evaluates the challenge data and generates a response.118* If a challenge is received from the server during the authentication119* process, this method is called to prepare an appropriate next120* response to submit to the server.121*122* @param challenge The non-null challenge sent from the server.123* The challenge array may have zero length.124*125* @return The possibly null response to send to the server.126* It is null if the challenge accompanied a "SUCCESS" status and the challenge127* only contains data for the client to update its state and no response128* needs to be sent to the server. The response is a zero-length byte129* array if the client is to send a response with no data.130* @exception SaslException If an error occurred while processing131* the challenge or generating a response.132*/133public abstract byte[] evaluateChallenge(byte[] challenge)134throws SaslException;135136/**137* Determines whether the authentication exchange has completed.138* This method may be called at any time, but typically, it139* will not be called until the caller has received indication140* from the server141* (in a protocol-specific manner) that the exchange has completed.142*143* @return true if the authentication exchange has completed; false otherwise.144*/145public abstract boolean isComplete();146147/**148* Unwraps a byte array received from the server.149* This method can be called only after the authentication exchange has150* completed (i.e., when {@code isComplete()} returns true) and only if151* the authentication exchange has negotiated integrity and/or privacy152* as the quality of protection; otherwise, an153* {@code IllegalStateException} is thrown.154* <p>155* {@code incoming} is the contents of the SASL buffer as defined in RFC 2222156* without the leading four octet field that represents the length.157* {@code offset} and {@code len} specify the portion of {@code incoming}158* to use.159*160* @param incoming A non-null byte array containing the encoded bytes161* from the server.162* @param offset The starting position at {@code incoming} of the bytes to use.163* @param len The number of bytes from {@code incoming} to use.164* @return A non-null byte array containing the decoded bytes.165* @exception SaslException if {@code incoming} cannot be successfully166* unwrapped.167* @exception IllegalStateException if the authentication exchange has168* not completed, or if the negotiated quality of protection169* has neither integrity nor privacy.170*/171public abstract byte[] unwrap(byte[] incoming, int offset, int len)172throws SaslException;173174/**175* Wraps a byte array to be sent to the server.176* This method can be called only after the authentication exchange has177* completed (i.e., when {@code isComplete()} returns true) and only if178* the authentication exchange has negotiated integrity and/or privacy179* as the quality of protection; otherwise, an180* {@code IllegalStateException} is thrown.181* <p>182* The result of this method will make up the contents of the SASL buffer183* as defined in RFC 2222 without the leading four octet field that184* represents the length.185* {@code offset} and {@code len} specify the portion of {@code outgoing}186* to use.187*188* @param outgoing A non-null byte array containing the bytes to encode.189* @param offset The starting position at {@code outgoing} of the bytes to use.190* @param len The number of bytes from {@code outgoing} to use.191* @return A non-null byte array containing the encoded bytes.192* @exception SaslException if {@code outgoing} cannot be successfully193* wrapped.194* @exception IllegalStateException if the authentication exchange has195* not completed, or if the negotiated quality of protection196* has neither integrity nor privacy.197*/198public abstract byte[] wrap(byte[] outgoing, int offset, int len)199throws SaslException;200201/**202* Retrieves the negotiated property.203* This method can be called only after the authentication exchange has204* completed (i.e., when {@code isComplete()} returns true); otherwise, an205* {@code IllegalStateException} is thrown.206* <p>207* The {@link Sasl} class includes several well-known property names208* (For example, {@link Sasl#QOP}). A SASL provider can support other209* properties which are specific to the vendor and/or a mechanism.210*211* @param propName The non-null property name.212* @return The value of the negotiated property. If null, the property was213* not negotiated or is not applicable to this mechanism.214* @exception IllegalStateException if this authentication exchange215* has not completed216*/217public abstract Object getNegotiatedProperty(String propName);218219/**220* Disposes of any system resources or security-sensitive information221* the SaslClient might be using. Invoking this method invalidates222* the SaslClient instance. This method is idempotent.223* @throws SaslException If a problem was encountered while disposing224* the resources.225*/226public abstract void dispose() throws SaslException;227}228229230