1 /* 2 * Copyright (c) 1999, 2003, 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 26 package javax.security.sasl; 27 28 /** 29 * Performs SASL authentication as a client. 30 *<p> 31 * A protocol library such as one for LDAP gets an instance of this 32 * class in order to perform authentication defined by a specific SASL 33 * mechanism. Invoking methods on the <tt>SaslClient</tt> instance 34 * process challenges and create responses according to the SASL 35 * mechanism implemented by the <tt>SaslClient</tt>. 36 * As the authentication proceeds, the instance 37 * encapsulates the state of a SASL client's authentication exchange. 38 *<p> 39 * Here's an example of how an LDAP library might use a <tt>SaslClient</tt>. 40 * It first gets an instance of a <tt>SaslClient</tt>: 41 *<blockquote><pre>{@code 42 * SaslClient sc = Sasl.createSaslClient(mechanisms, 43 * authorizationId, protocol, serverName, props, callbackHandler); 44 *}</pre></blockquote> 45 * It can then proceed to use the client for authentication. 46 * For example, an LDAP library might use the client as follows: 47 *<blockquote><pre>{@code 48 * // Get initial response and send to server 49 * byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[0]) : 50 * null); 51 * LdapResult res = ldap.sendBindRequest(dn, sc.getName(), response); 52 * while (!sc.isComplete() && 53 * (res.status == SASL_BIND_IN_PROGRESS || res.status == SUCCESS)) { 54 * response = sc.evaluateChallenge(res.getBytes()); 55 * if (res.status == SUCCESS) { 56 * // we're done; don't expect to send another BIND 57 * if (response != null) { 58 * throw new SaslException( 59 * "Protocol error: attempting to send response after completion"); 60 * } 61 * break; 62 * } 63 * res = ldap.sendBindRequest(dn, sc.getName(), response); 64 * } 65 * if (sc.isComplete() && res.status == SUCCESS) { 66 * String qop = (String) sc.getNegotiatedProperty(Sasl.QOP); 67 * if (qop != null 68 * && (qop.equalsIgnoreCase("auth-int") 69 * || qop.equalsIgnoreCase("auth-conf"))) { 70 * 71 * // Use SaslClient.wrap() and SaslClient.unwrap() for future 72 * // communication with server 73 * ldap.in = new SecureInputStream(sc, ldap.in); 74 * ldap.out = new SecureOutputStream(sc, ldap.out); 75 * } 76 * } 77 *}</pre></blockquote> 78 * 79 * If the mechanism has an initial response, the library invokes 80 * <tt>evaluateChallenge()</tt> with an empty 81 * challenge and to get initial response. 82 * Protocols such as IMAP4, which do not include an initial response with 83 * their first authentication command to the server, initiates the 84 * authentication without first calling <tt>hasInitialResponse()</tt> 85 * or <tt>evaluateChallenge()</tt>. 86 * When the server responds to the command, it sends an initial challenge. 87 * For a SASL mechanism in which the client sends data first, the server should 88 * have issued a challenge with no data. This will then result in a call 89 * (on the client) to <tt>evaluateChallenge()</tt> with an empty challenge. 90 * 91 * @since 1.5 92 * 93 * @see Sasl 94 * @see SaslClientFactory 95 * 96 * @author Rosanna Lee 97 * @author Rob Weltman 98 */ 99 public abstract interface SaslClient { 100 101 /** 102 * Returns the IANA-registered mechanism name of this SASL client. 103 * (e.g. "CRAM-MD5", "GSSAPI"). 104 * @return A non-null string representing the IANA-registered mechanism name. 105 */ 106 public abstract String getMechanismName(); 107 108 /** 109 * Determines whether this mechanism has an optional initial response. 110 * If true, caller should call <tt>evaluateChallenge()</tt> with an 111 * empty array to get the initial response. 112 * 113 * @return true if this mechanism has an initial response. 114 */ 115 public abstract boolean hasInitialResponse(); 116 117 /** 118 * Evaluates the challenge data and generates a response. 119 * If a challenge is received from the server during the authentication 120 * process, this method is called to prepare an appropriate next 121 * response to submit to the server. 122 * 123 * @param challenge The non-null challenge sent from the server. 124 * The challenge array may have zero length. 125 * 126 * @return The possibly null reponse to send to the server. 127 * It is null if the challenge accompanied a "SUCCESS" status and the challenge 128 * only contains data for the client to update its state and no response 129 * needs to be sent to the server. The response is a zero-length byte 130 * array if the client is to send a response with no data. 131 * @exception SaslException If an error occurred while processing 132 * the challenge or generating a response. 133 */ 134 public abstract byte[] evaluateChallenge(byte[] challenge) 135 throws SaslException; 136 137 /** 138 * Determines whether the authentication exchange has completed. 139 * This method may be called at any time, but typically, it 140 * will not be called until the caller has received indication 141 * from the server 142 * (in a protocol-specific manner) that the exchange has completed. 143 * 144 * @return true if the authentication exchange has completed; false otherwise. 145 */ 146 public abstract boolean isComplete(); 147 148 /** 149 * Unwraps a byte array received from the server. 150 * This method can be called only after the authentication exchange has 151 * completed (i.e., when <tt>isComplete()</tt> returns true) and only if 152 * the authentication exchange has negotiated integrity and/or privacy 153 * as the quality of protection; otherwise, an 154 * <tt>IllegalStateException</tt> is thrown. 155 *<p> 156 * <tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 157 * without the leading four octet field that represents the length. 158 * <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt> 159 * to use. 160 * 161 * @param incoming A non-null byte array containing the encoded bytes 162 * from the server. 163 * @param offset The starting position at <tt>incoming</tt> of the bytes to use. 164 * @param len The number of bytes from <tt>incoming</tt> to use. 165 * @return A non-null byte array containing the decoded bytes. 166 * @exception SaslException if <tt>incoming</tt> cannot be successfully 167 * unwrapped. 168 * @exception IllegalStateException if the authentication exchange has 169 * not completed, or if the negotiated quality of protection 170 * has neither integrity nor privacy. 171 */ 172 public abstract byte[] unwrap(byte[] incoming, int offset, int len) 173 throws SaslException; 174 175 /** 176 * Wraps a byte array to be sent to the server. 177 * This method can be called only after the authentication exchange has 178 * completed (i.e., when <tt>isComplete()</tt> returns true) and only if 179 * the authentication exchange has negotiated integrity and/or privacy 180 * as the quality of protection; otherwise, an 181 * <tt>IllegalStateException</tt> is thrown. 182 *<p> 183 * The result of this method will make up the contents of the SASL buffer 184 * as defined in RFC 2222 without the leading four octet field that 185 * represents the length. 186 * <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>outgoing</tt> 187 * to use. 188 * 189 * @param outgoing A non-null byte array containing the bytes to encode. 190 * @param offset The starting position at <tt>outgoing</tt> of the bytes to use. 191 * @param len The number of bytes from <tt>outgoing</tt> to use. 192 * @return A non-null byte array containing the encoded bytes. 193 * @exception SaslException if <tt>outgoing</tt> cannot be successfully 194 * wrapped. 195 * @exception IllegalStateException if the authentication exchange has 196 * not completed, or if the negotiated quality of protection 197 * has neither integrity nor privacy. 198 */ 199 public abstract byte[] wrap(byte[] outgoing, int offset, int len) 200 throws SaslException; 201 202 /** 203 * Retrieves the negotiated property. 204 * This method can be called only after the authentication exchange has 205 * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an 206 * <tt>IllegalStateException</tt> is thrown. 207 * 208 * @param propName The non-null property name. 209 * @return The value of the negotiated property. If null, the property was 210 * not negotiated or is not applicable to this mechanism. 211 * @exception IllegalStateException if this authentication exchange 212 * has not completed 213 */ 214 215 public abstract Object getNegotiatedProperty(String propName); 216 217 /** 218 * Disposes of any system resources or security-sensitive information 219 * the SaslClient might be using. Invoking this method invalidates 220 * the SaslClient instance. This method is idempotent. 221 * @throws SaslException If a problem was encountered while disposing 222 * the resources. 223 */ 224 public abstract void dispose() throws SaslException; 225 }