title: How to use the Java SASL API and CRAM-MD5
body: <p>I'm currently playing with the Java SASL API and I wrote a little program to simulate a challenge response sequence using CRAM-MD5. However, I'm unsure about how to do this, as SaslClient and SaslServer only have methods evaluateChallenge(...) and evaluateResponse(...). I would expect SaslServer to have a method like issueChallenge(...) or something like that, but it has not. So what is the correct way to do this?</p>
  
  <p>Below you find my (not working) code.</p>
  
  <pre><code>    package mypackage;
  
      import java.io.IOException;
  
      import javax.security.auth.callback.Callback;
      import javax.security.auth.callback.CallbackHandler;
      import javax.security.auth.callback.NameCallback;
      import javax.security.auth.callback.PasswordCallback;
      import javax.security.auth.callback.UnsupportedCallbackException;
      import javax.security.sasl.AuthorizeCallback;
      import javax.security.sasl.Sasl;
      import javax.security.sasl.SaslClient;
      import javax.security.sasl.SaslException;
      import javax.security.sasl.SaslServer;
  
      public class Main {
  
      public static void main(String[] args) throws SaslException {
  
    new Main().start();
   }
  
   private static class ClientHandler implements CallbackHandler {
  
    @Override
    public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
     for (Callback cb : cbs) {
      if (cb instanceof NameCallback) {
  
       System.out.println("Client - NameCallback");
  
       NameCallback nc = (NameCallback)cb;
       nc.setName("username");
      } else if (cb instanceof PasswordCallback) {
  
       System.out.println("Client - PasswordCallback");
  
       PasswordCallback pc = (PasswordCallback)cb;
       pc.setPassword("password".toCharArray());
      }
     }
    }
   }
  
   private static class ServerHandler implements CallbackHandler {
  
    @Override
    public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
     for (Callback cb : cbs) {
      if (cb instanceof AuthorizeCallback) {
  
       System.out.println("Server - AuthorizeCallback");
  
       AuthorizeCallback ac = (AuthorizeCallback)cb;
       ac.setAuthorized(true);
  
      } else if (cb instanceof NameCallback) {
  
       System.out.println("Server - NameCallback");
  
       NameCallback nc = (NameCallback)cb;
       nc.setName("username");
  
      } else if (cb instanceof PasswordCallback) {
  
       System.out.println("Server - PasswordCallback");
  
       PasswordCallback pc = (PasswordCallback)cb;
       pc.setPassword("password".toCharArray());
      }
     }
    }
   }
  
   private void start() throws SaslException {
  
    byte[] challenge;
    byte[] response;
  
    ClientHandler clientHandler = new ClientHandler();
    ServerHandler serverHandler = new ServerHandler();
  
    SaslClient sc = Sasl.createSaslClient(new String[] { "CRAM-MD5" }, null, "my_server", "FQHN", null, clientHandler); 
    SaslServer ss = Sasl.createSaslServer("CRAM-MD5", "my_server", "FQHN", null, serverHandler);
  
    // Challenge response sequence (not working)
    challenge = ss.evaluateResponse(null);
    response = sc.evaluateChallenge(challenge);
    ss.evaluateResponse(response);
  
    if (ss.isComplete()) {
     System.out.println("Authentication successful.");
    }
   }
  }
  </code></pre>
  
  <p>Greetings, Fred</p>