Internet Draft Rob Weltman Netscape Communications Corp. Rosanna Lee draft-weltman-java-sasl-02.txt Sun Microsystems Rob Earhart Carnegie Mellon June 4, 1999 The Java SASL Application Program Interface Status of this Memo This document is an Internet-Draft and is in full conformance with all provisions of Section 10 of RFC2026. Internet-Drafts are working documents of the Internet Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet Drafts as reference material or to cite them other than as "work in progress." The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html. Abstract This document defines a client-side and a server-side Java language interface for using the Simple Authentication and Security Layer (SASL) mechanisms for adding authentication support to connection- based protocols. The interface promotes sharing of SASL mechanism drivers and security layers between applications using different protocols. It complements but does not replace [SASL], which defines and exemplifies use of the SASL protocol in a language-independent way. Expires 12/99 [Page 1] JAVA SASL API June 1999 1 Overview of the SASL classes..........................5 1.1 Interfaces .......................................5 1.2 Classes .......................................5 2 Overview of SASL API Use..............................6 3 The java SASL classes.................................7 3.1 public class Sasl.....................................7 3.1.1 createSaslClient.................................7 3.1.2 setSaslClientFactory.............................9 3.1.3 createSaslServer.................................9 3.1.4 setSaslServerFactory............................10 3.2 public interface SaslClient..........................11 3.2.1 createInitialResponse...........................11 3.2.2 evaluateChallenge...............................11 3.2.3 isComplete......................................11 3.2.4 getSecurityLayer................................11 3.2.5 getMechanismName................................12 3.3 public interface SaslClientFactory...................12 3.3.1 createSaslClient................................12 3.3.2 getMechanismNames...............................13 3.4 public interface SaslServer..........................13 3.4.1 evaluateResponse................................13 3.4.2 isComplete......................................14 3.4.3 getSecurityLayer................................14 3.4.4 getMechanismName................................14 3.4.5 getAuthorizationID..............................14 3.5 public interface SaslServerFactory...................15 3.5.1 createSaslServer................................15 3.5.2 getMechanismNames...............................16 3.6 public class SaslException...........................16 3.6.1 Constructors....................................16 3.6.2 getException....................................17 3.6.3 printStackTrace.................................17 3.7 public interface SecurityLayer.......................17 3.7.1 encode......................................17 3.7.2 decode......................................18 4 Security Considerations..............................19 5 Bibliography ......................................19 6 Authors' Addresses...................................19 7 Acknowledgements.....................................19 8 Appendix A - Sample java LDAP program using SASL.....20 9 Appendix B - Changes from java-sasl-01.txt...........24 Expires 12/99 [Page 2] JAVA SASL API June 1999 Introduction See [SASL], section 3, for an introduction to and overview of the SASL framework for authentication and negotiation of a security layer. The following presents an outline of the concepts. --------------- ------------------- ----------------- | Application |-----| Protocol Driver |------| MD5 | --------------- ------------------- | ----------------- | | ----------------- |--| Kerberos v5 | | ----------------- | | ----------------- |--| PKCS-11 | | ----------------- | | | | - - - - - - - - - |--| xxxYYYxxx | - - - - - - - - - An application chooses a Protocol Driver specific to the protocol it wants to use, and specifies one or more acceptable mechanisms. The Protocol Driver controls the socket, and knows the format/packaging of bytes sent down and received from the socket, but does not know how to authenticate or to encrypt/ decrypt the bytes. It uses one of the Mechanism Drivers to help it perform authentication. The Protocol Driver examines each byte string received from the server during the authentication in a protocol-specific way to determine if the authentication process has been completed. If not, the byte string is passed to the Mechanism Driver to be interpreted as a server challenge; the Mechanism Driver returns an appropriate response, which the Protocol Driver can encode in a protocol- specific way and return to the server. If the Protocol Driver concludes from the byte string received from the server that authentication is complete, it may query the Mechanism Driver if it considers the authentication process complete, in order to thwart early completion messages inserted by an intruder. On completed authentication, the Protocol Driver may receive from the Mechanism Driver a Security Layer object. From this point on, any data exchanged throught the socket is passed to the Security Layer object for encoding/decoding. A complication here is that some authentication methods may require additional user/application input. That means that a Mechanism Driver may need to call up to an application during the authentication process. To satisfy this requirement, the application Expires 12/99 [Page 3] JAVA SASL API June 1999 can supply a javax.security.auth.callback.CallbackHandler instance [JAAS] that can be used by the Mechanism Driver to prompt the user for additional input. Protocol Drivers are protocol-dependent, and may be built in to a protocol package or an application. There is a generalized framework for registering and finding Mechanism Drivers. The framework uses a factory to produce an appropriate Mechanism Driver. The factory may be preconfigured, explicitly specified by the caller, specified as a list of packages by the caller, or be identified based on a list of packages in the System properties. The Mechanism Drivers are protocol-independent, and don't deal directly with network connections, just byte arrays, so they can be implemented in a generalizable way for all protocols. A Security Layer Driver typically inherits a state object from the Mechanism Driver, where parameters and resolutions reached during authentication have been stored. Different Mechanism Drivers may require different parameters to carry out the authentication process. This is handled by passing a java.util.Hashtable object as an argument to instantiation methods. In the following discussion, 'client' refers to the client-side protocol driver that is using the SASL mechanism while 'server' refers to the server-side protocol driver that is using the SASL mechanism. In the Java SASL environment, the SaslClient interface represents the client's view of the Mechanism Driver, while the SaslServer interface represents the server's view. --------------- --------------- | Application |--+ +--| Server | --------------- | | --------------- | | ------------------- ------------------- | Protocol Driver |--+ <- - - - -> +--| Protocol Driver | ------------------- | | ------------------- | | ------------------- ------------------- | SaslClient | | SaslServer | ------------------- ------------------- | | ----------------- | | ----------------- | MD5 |----| |---| MD5 | ----------------- | | ----------------- | | ----------------- | | ----------------- | Kerberos v5 |----| |---| Kerberos v5 | ----------------- | | ----------------- | | ----------------- | | ----------------- Expires 12/99 [Page 4] JAVA SASL API June 1999 | PKCS-11 |----| |---| PKCS-11 | ----------------- | | ----------------- | | - - - - - - - - - | | - - - - - - - - - | xxxYYYxxx |----+ +---| xxxYYYxxx | - - - - - - - - - - - - - - - - - - A client using the Java SASL API may communicate with any server implementing the SASL protocol, and a server may use the API to process authentication requests from any client using the SASL protocol. It is not required that both sides use the same language bindings. 1 Overview of the SASL classes 1.1 Interfaces SaslClient Performs SASL authentication as a client. SaslClientFactory An interface for creating instances of SaslClient. It is not normally accessed directly by a client, which will use the Sasl static methods instead. However, a particular environment may provide and install a new or different SaslClientFactory. SaslServer Performs SASL authentication as a server. SaslServerFactory An interface for creating instances of SaslServer. It is not normally accessed directly by a server, which will use the Sasl static methods instead. However, a particular environment may provide and install a new or different SaslServerFactory. SecurityLayer An interface for encoding and decoding data. 1.2 Classes Sasl A static class for creating SASL clients and servers. It transparently locates and uses any available SaslClientFactory/SaslServerFactory instances. Expires 12/99 [Page 5] JAVA SASL API June 1999 SaslException Exception thrown on errors and failures in the authentication process. 2 Overview of SASL API Use An application generally uses the SASL API as follows: - Pass a list of acceptable or known Mechanisms to Sasl.createSaslClient. The method returns an object implementing SaslClient on success. - Create an object implementing the client authentication callback interfaces, which can provide credentials when required by the SaslClient. - Have the SaslClient object begin the authentication process by providing an initial server response, if the protocol supports an initial response. - Responses/challenges are exchanged with the server. If a response indicates authentication has completed, SaslClient is queried for validation, and a SecurityLayer object may be obtained from it. If not, the SaslClient is queried for an appropriate next response to the server. This continues until authentication has completed. - For the rest of the session, messages to the server are encoded first by the Security Layer (if one has been provided by SaslClient), and messages from the server are decoded by it before processing in the application. A server generally uses the SASL API as follows: - It receives a request from the client requesting authentication for a particular SASL mechanism, accompanied by an optional an initial response. - It processes the initial response and generates a challenge specific for the SASL mechanism to be sent back to the client if the response is processed successfully. If the response is not processed successfully, it sends an error to the client and terminates the authentication session. - Responses/challenges are exchanged with the client. If the server cannot successful process a response, the server sends an error to the client and terminates the authentication. If the server has completed the authentication and has no more challenges to send, it sends a success indication to the client. - If the authentication has completed successfully, the server extracts the authorization ID of the client from the SaslServer Expires 12/99 [Page 6] JAVA SASL API June 1999 instance (if appropriate) to be used for subsequent access control checks. - For the rest of the session, messages to and from the client are encoded and decoded by the Security Layer, if one has been provided by SaslServer. The following sections describe the SASL classes in more detail. 3 The Java SASL classes 3.1 public class Sasl A class capable of providing a SaslClient or SaslServer. 3.1.1 createSaslClient public static SaslClient createSaslClient(String[] mechanisms, String authorizationID, String protocol, String serverName, Hashtable props, javax.security.auth.callback.CallbackHandler cbh) throws SaslException Creates a SaslClient using the parameters supplied. It returns null if no SaslClient can be created using the parameters supplied. Throws SaslException if it cannot create a SaslClient because of an error. The algorithm for selection is as follows: 1.If a factory has been installed via setSaslClientFactory(), try it first. If non-null answer produced, return it. 2.Use the packages listed in the javax.security.sasl.client.pkgs property from props to load in a factory and try to create a SaslClient, by looking for a class named ClientFactory. Repeat this for each package on the list until a non-null answer is produced. If non-null answer produced, return it. 3.Repeat previous step using the javax.security.sasl.client.pkgs System property. 4.If no non-null answer produced, return null. Parameters are: mechanisms The non-null list of mechanism names to try. Each is the IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). Expires 12/99 [Page 7] JAVA SASL API June 1999 authorizationIDThe possibly null protocol-dependent identification to be used for authorization, e.g. user name or distinguished name. When the SASL authentication completes successfully, the entity named by authorizationId is granted access. If null, access is granted to a protocol-dependent default (for example, in LDAP this is the DN in the bind request). protocol The non-null string name of the protocol for which the authentication is being performed, e.g "pop", "ldap". serverName The non-null fully qualified host name of the server to authenticate to. props The possibly null additional configuration properties for the session, e.g. javax.security.sasl.encryption.minimum Minimum key length; default "0" (no session protection). "1" means integrity protection only. javax.security.sasl.encryption.maximum Maximum key length; default "256". javax.security.sasl.server.authentication "true" if server must authenticate to client; default "false". javax.security.sasl.ip.local IP address in dotted decimal format, for kerberos v4; no default. javax.security.sasl.ip.remote IP address in dotted decimal format, for kerberos v4; no default. javax.security.sasl.maxbuffer Maximum size of security layer frames; default "0" (client will not use the security layer). Expires 12/99 [Page 8] JAVA SASL API June 1999 javax.security.sasl.client.pkgs A space-separated list of package names to use when locating a SaslClientFactory. cbh The possibly null callback handler to used by the SASL mechanisms to get further information from the application/library to complete the authentication. For example, a SASL mechanism might require the authentication ID and password from the caller. The authentication ID may be requested with a NameCallback, and the password with a PasswordCallback. 3.1.2 setSaslClientFactory public static void setSaslClientFactory(SaslClientFactory fac) Sets the default SaslClientFactory to use. This method sets fac to be the default factory. It can only be called with a non-null value once per VM. If a factory has been set already, this method throws IllegalStateException. Parameters are: fac The possibly null factory to set. If null, it doesn't do anything. 3.1.3 createSaslServer public static SaslServer createSaslServer(String mechanism, String protocol, String serverName, Hashtable props, javax.security.auth.callback.CallbackHandler cbh) throws SaslException This method creates a SaslServer for the specified mechanism. It returns null if no SaslServer can be created for the specified mechanism. The algorithm for selection is as follows: 1.If a factory has been installed via setSaslServerFactory(), try it first. If non-null answer produced, return it. 2.Use the packages listed in the javax.security.sasl.server.pkgs property in props, if present, to load in a factory and try to create a SaslServer, by looking for a class named Expires 12/99 [Page 9] JAVA SASL API June 1999 ServerFactory. Repeat this for each package on the list until a non-null answer is produced. If non-null answer produced, return it. 3.Use the packages listed in the javax.security.sasl.server.pkgs System property to load in a factory and try to create a SaslServer. Repeat this for each package on the list until a non-null answer is produced. If non-null answer produced, return it. 4.If no non-null answer produced, return null. Parameters are: mechanism A non-null IANA-registered name of a SASL mechanism (e.g. "GSSAPI", "CRAM-MD5"). protocol The non-null string name of the protocol for which the authentication is being performed, e.g "pop", "ldap". serverName The non-null fully qualified host name of the server to authenticate to. props The possibly null properties to be used by the SASL mechanisms to configure the authentication exchange. See Sasl.createSaslClient for examples of properties. cbh The possibly null callback handler to used by the SASL mechanisms to get further information from the application/library to complete the authentication. For example, a SASL mechanism might require the authentication ID and password from the caller. The authentication ID may be requested with a NameCallback, and the password with a PasswordCallback. 3.1.4 setSaslServerFactory public static void setSaslServerFactory(SaslServerFactory fac) Sets the default SaslServerFactory to use. This method sets fac to be the default factory. It can only be called with a non-null value once per VM. If a factory has been set already, this method throws IllegalStateException. Parameters are: fac The possibly null factory to set. If null, it doesn't do anything. Expires 12/99 [Page 10] JAVA SASL API June 1999 3.2 public interface SaslClient An object implementing this interface can negotiate authentication using one of the IANA-registered mechanisms. 3.2.1 createInitialResponse public byte[] createInitialResponse() throws SaslException This method prepares a byte array to use for the initial response to start the authentication process. A SaslException is thrown if the driver cannot initiate authentication. The return value may be null, indicating there is no initial response to send to the server. 3.2.2 evaluateChallenge public byte[] evaluateChallenge(byte[] challenge) throws SaslException If a challenge is received from the server during the authentication process, this method is called to prepare an appropriate next response to submit to the server. The response is null if the challenge accompanied a "SUCCESS" status and the challenge only contains data for the client to update its state and no response needs to be sent to the server. A SaslException is thrown if an error occurred while processing the challenge or generating a response. Parameters are: challenge The non-null challenge received from the server. 3.2.3 isComplete public boolean isComplete() This method may be called at any time to determine if the authentication process is finished. Typically, the protocol driver will not do this until it has received something from the server which indicates (in a protocol-specific manner) that the process has completed. 3.2.4 getSecurityLayer public SecurityLayer getSecurityLayer() throws SaslException Expires 12/99 [Page 11] JAVA SASL API June 1999 Once authentication is complete, this method may be called to obtain an object capable of encoding/decoding data content for the rest of the session. An exception is thrown if authentication is not yet complete. It may return null if the mechanism does not define a security layer, or if none was negotiated. 3.2.5 getMechanismName public String getMechanismName() Report the IANA-registered name of the mechanism used by this client, e.g. "GSSAPI" or "CRAM-MD5". 3.3 public interface SaslClientFactory An object implementing this interface can provide a SaslClient. Implementations must be thread-safe and handle multiple simultaneous requests. 3.3.1 createSaslClient public SaslClient createSaslClient(String[] mechanisms, String authorizationID, String protocol, String serverName, Hashtable props, javax.security.auth.callback.CallbackHandler cbh) throws SaslException Creates a SaslClient using the parameters supplied. It returns null if no SaslClient can be created using the parameters supplied. Throws SaslException if it cannot create a SaslClient because of an error. Returns a possibly null SaslClient created using the parameters supplied. If null, this factory cannot produce a SaslClient using the parameters supplied. Parameters are: mechanisms The non-null list of mechanism names to try. Each is the IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5"). authorizationID The possibly null protocol-dependent identification to be used for authorization, e.g. user name or distinguished name. When the SASL authentication completes successfully, the entity Expires 12/99 [Page 12] JAVA SASL API June 1999 named by authorizationId is granted access. If null, access is granted to a protocol-dependent default (for example, in LDAP this is the DN in the bind request). protocol The non-null string name of the protocol for which the authentication is being performed, e.g "pop", "ldap". serverName The non-null fully qualified host name of the server to authenticate to. props The possibly null properties to be used by the SASL mechanisms to configure the authentication exchange. See Sasl.createSaslClient for examples of properties. cbh The possibly null callback handler to used by the SASL mechanisms to get further information from the application/library to complete the authentication. For example, a SASL mechanism might require the authentication ID and password from the caller. The authentication ID may be requested with a NameCallback, and the password with a PasswordCallback. 3.3.2 getMechanismNames public String[] getMechanismNames() Returns a non-null array of names of mechanisms supported by this factory. 3.4 public interface SaslServer An object implementing this interface can negotiate authentication using one of the IANA-registered mechanisms. 3.4.1 evaluateResponse public byte[] evaluateResponse(byte[] response) throws SaslException If a response is received from the client during the authentication process, this method is called to prepare an appropriate next challenge to submit to the client. The challenge is null if the authentication has succeeded and no more challenge data is to be sent to the client. It is non-null if the authentication must be Expires 12/99 [Page 13] JAVA SASL API June 1999 continued by sending a challenge to the client, or if the authentication has succeeded but challenge data needs to be processed by the client. A SaslException is thrown if an error occurred while processing the response or generating a challenge. isComplete() should be called after each call to evaluateResponse(), to determine if any further response is needed from the client. The protocol driver will send an indication (in a protocol-specific manner) as to whether the authentication has succeeded, failed, or should be continued, and any accompanying challenge data. Parameters are: response Non-null response received from client. 3.4.2 isComplete public boolean isComplete() This method may be called at any time to determine if the authentication process is finished. This method is typically called after each invocation of evaluateResponse() to determine whether the authentication has completed successfully or should be continued. 3.4.3 getSecurityLayer public SecurityLayer getSecurityLayer() throws SaslException Once authentication is complete, this method may be called to obtain an object capable of encoding/decoding data content for the rest of the session. An exception is thrown if authentication is not yet complete. It may return null if the mechanism does not define a security layer, or if none was negotiated. 3.4.4 getMechanismName public String getMechanismName() Returns the non-null IANA-registered name of the mechanism used by this server, e.g. "GSSAPI" or "CRAM-MD5". 3.4.5 getAuthorizationID public String getAuthorizationID() Report the authorization ID in effect for the client of this session. If null, a protocol-dependent default is assumed. Expires 12/99 [Page 14] JAVA SASL API June 1999 3.5 public interface SaslServerFactory An object implementing this interface can provide a SaslServer. Implementations must be thread-safe and handle multiple simultaneous requests. 3.5.1 createSaslServer public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Hashtable props, javax.security.auth.callback.CallbackHandler cbh) throws SaslException Creates a SaslServer using the mechanism supplied. It returns null if no SaslClient can be created using the parameters supplied. Throws SaslException if it cannot create a SaslClient because of an error. Returns a possibly null SaslServer which supports the specified mechanism. If null, this factory cannot produce a SaslServer for the specified mechanism. Parameters are: mechanism The non-null IANA-registered name of a SASL mechanism (e.g. "GSSAPI", "CRAM-MD5"). protocol The non-null string name of the protocol for which the authentication is being performed, e.g "pop", "ldap". serverName The non-null fully qualified host name of the server. props The possibly null properties to be used by the SASL mechanisms to configure the authentication exchange. See Sasl.createSaslClient for examples of properties. cbh The possibly null callback handler to used by the SASL mechanisms to get further information from the application/library to complete the authentication. For example, a SASL mechanism might require the authentication ID and password from the caller. The authentication ID may be requested with a NameCallback, and the password with a PasswordCallback. Expires 12/99 [Page 15] JAVA SASL API June 1999 3.5.2 getMechanismNames public String[] getMechanismNames() Returns a non-null array of names of mechanisms supported by this factory. 3.6 public class SaslException extends IOException Exception thrown on errors and failures in authentication. 3.6.1 Constructors public SaslException() Constructs a new instance of SaslException. The root exception and the detailed message are null. public SaslException(String message) Constructs a default exception with a detailed message and no root exception. public SaslException(String messag, Throwable ex) Constructs a new instance of SaslException with a detailed message and a root exception. For example, a SaslException might result from a problem with the callback handler, which might throw a NoSuchCallbackException if it does not support the requested callback, or throw an IOException if it had problems obtaining data for the callback. The SaslException's root exception would be then be the exception thrown by the callback handler. Parameters are: message Possibly null additional detail about the exception. ex A possibly null root exception that caused this exception. Expires 12/99 [Page 16] JAVA SASL API June 1999 3.6.2 getException public Throwable getException() Returns the possibly null root exception that caused this exception. 3.6.3 printStackTrace public void printStackTrace() Prints this exception's stack trace to System.err. If this exception has a root exception, the stack trace of the root exception is printed to System.err instead. public void printStackTrace(PrintStream ps) Prints this exception's stack trace to a print stream. If this exception has a root exception, the stack trace of the root exception is printed to the print stream instead. public void printStackTrace(PrintWriter pw) Prints this exception's stack trace to a print writer. If this exception has a root exception, the stack trace of the root exception is printed to the print writer instead. Parameters are: ps The non-null print stream to which to print. pw The non-null print writer to which to print. 3.7 public interface SecurityLayer An object implementing this interface translates buffers back and forth during a session, after the authentication process has completed, to provide a security layer. The security layer may provide data integrity and/or session privacy. 3.7.1 encode public byte[] encode(byte[] inVals, int offset, int count) throws SASLException Take a protocol-dependent byte array and encode it (encrypt, for example) for sending to the server. Expires 12/99 [Page 17] JAVA SASL API June 1999 Parameters are: inVals A request to be encoded before sending to the server. offset The inclusive starting offset in the byte array inVals to use. 0 <= offset < inVals.length. count The number of bytes in inVals to use. 0 <= count < inVals.length-offset. 3.7.2 decode public byte[] decode(byte[] outVals, int offset, int count) throws SASLException Take an encoded byte array received from the server and decode it. Parameters are: outVals A response received from the server, to be decoded. offset The inclusive starting offset in the byte array outVals to use. 0 <= offset < outVals.length. count The number of bytes in outVals to use. 0 <= count < outVals.length-offset. Expires 12/99 [Page 18] JAVA SASL API June 1999 4 Security Considerations When SASL authentication is performed over unsecured connections, it is possible for an active attacker to spoof the server's protocol- specific indication that authentication is complete. Clients should protect against this attack by verifying the completion of authentication with the mechanism driver by calling the driver's isComplete() method. Additional security considerations are discussed in [SASL]. 5 Bibliography [JAAS] Java Software, Sun Microsystems, Inc., "Java Authentication and Authorization Service," http://java.sun.com/security/jaas, March 1999. [SASL] J. Myers, "Simple Authentication and Security Layer (SASL)", RFC 2222, October 1997 6 Authors' Addresses Rob Weltman Netscape Communications Corp. 501 E. Middlefield Rd. Mail Stop MV-029 Mountain View, CA 94043-4042 USA Email: rweltman@netscape.com Rosanna Lee Sun Microsystems Mail Stop UCUP02-206 901 San Antonio Road Palo Alto, CA 94303 USA Email: rosanna.lee@eng.sun.com Rob Earhart Carnegie Mellon 5000 Forbes Ave. Pittsburgh, PA 15213-3890 USA Email: earhart@cmu.edu 7 Acknowledgements Scott Seligman of Sun Microsystems, Inc. contributed to the architecture and API proposed in this document. Expires 12/99 [Page 19] JAVA SASL API June 1999 8 Appendix A - Sample java LDAP program using SASL /**************************************************************** It might look like this in LDAP. The Protocol Driver is implemented as part of the authenticate method of LDAPConnection. ****************************************************************/ public class LDAPConnection { public void authenticate( String dn, String[] mechs, Hashtable props, CallbackHandler cbh ) throws SaslException { // Create SASL client to use for authentication SaslClient saslClnt = Sasl.createSaslClient( mechs, dn, "ldap", getHost(), props, cbh); if (saslClnt == null) { throw new SaslException("SASL client not available"); } String mechName = saslClnt.getMechanismName(); byte[] response = saslClnt.createInitialResponse(); // Create a bind request message, including the initial // response (if any), and send it off LDAPSASLBindResponse msg = writeRequest( new LDAPSASLBindRequest( dn, mechName, response ) ); // Get the server challenge LDAPSASLBindResponse msg = (LDAPSASLBindResponse)readResponse(); // Authentication done? while (!saslClnt.isComplete() && msg.getStatus() == LDAP_SASL_BIND_IN_PROGRESS) { // No, get an appropriate next response and send it off byte[] challenge = msg.getChallenge(); response = saslClnt.evaluateChallenge( challenge ); // May be a success message with no further challenge if ( response != null ) { // Wrap the response in another bind request and // send it off writeRequest( new LDAPSASLBindRequest( dn, mechName, response ) ); msg = (LDAPSASLBindResponse)readResponse(); } } // Make sure authentication REALLY is complete if ( !driver.isComplete() ) { /* Authentication session hijacked! */ throw new SaslException( "SASL session hijacked!" ); } // Get the negotiated security layer, if any Expires 12/99 [Page 20] JAVA SASL API June 1999 security = saslClnt.getSecurityLayer(); } Expires 12/99 [Page 21] JAVA SASL API June 1999 /**************************************************************** This might be in an application ****************************************************************/ /** * A sample callback handler. This implementation is created by * using the input that it will return. Other implementations are * typically more sophisticated and might prompt the user on demand * in order to satisfy the callbacks. */ class SimpleCallbackHandler implements CallbackHandler { private char[] passwd; private String authenticationID; SimpleCallbackHandler(String principal, Object cred) throws IOException { authenticationID = principal; if (cred instanceof String) { passwd = ((String)cred).toCharArray(); } else if (cred instanceof char[]) { passwd = (char[])((char[])cred).clone(); } else if (cred instanceof byte[]) { // PasswordCallback expects char[]; assume UTF-8 // encoding String orig = new String((byte[])cred, "UTF8"); passwd = orig.toCharArray(); } else { throw new IOException("Unsupported password format: " + cred); } } public void invokeCallback(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { ((NameCallback)callbacks[i]).setName( authenticationID); } else if (callbacks[i] instanceof PasswordCallback) { ((PasswordCallback)callbacks[i]).setPassword( passwd); } else { throw new UnsupportedCallbackException(callbacks[i]); } } } } Expires 12/99 [Page 22] JAVA SASL API June 1999 /*************************************************************** And so the application code to do authentication ***************************************************************/ // Set up all SASL parameters; some may have reasonable defaults Hashtable props = new Hashtable(); props.add("javax.security.sasl.encryption.minimum", "40"); props.add("javax.security.sasl.encryption.maximum", "128"); props.add("javax.security.sasl.server_authentication", "true"); props.add("javax.security.sasl.maxbuffer", "4096"); // The following two for kerberos v4, only //props.add("javax.security.sasl.ip.local", "192.68.1.10"); //props.add("javax.security.sasl.ip.remote", "192.68.1.50"); // What we want to authenticate as String dn = "cn=Directory Manager"; // Create an object for possible use by the authentication // process SimpleCallbackHandler cbh = new SimpleCallbackHandler(); try { // Note: cbh methods may be called during authentication // Note: "connection" includes the SASL Protocol Driver // functionality, and it will internally manage a Mechanism // Driver for GSSAPI, and then a Security Layer object for // data translation String[] mechNames = { "GSSAPI" }; connection.authenticate( dn, mechNames, props, cbh ); } catch ( SaslException e ) { // Abort, return, maybe try some other authentication } // Okay. From here on, everything goes through security, but the // methods have the same signatures as if we were not using SASL Expires 12/99 [Page 23] JAVA SASL API June 1999 9 Appendix B - Changes from draft-weltman-java-sasl-01.txt The class hierarchy defined in this document is entirely different from that defined in the previous document. For callback handling, the newly released javax.security.auth.callback package is used. Expires 12/99 [Page 24]