content: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package backtype.storm.security.auth.digest;
  
  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.RealmCallback;
  import javax.security.auth.login.AppConfigurationEntry;
  import javax.security.auth.login.Configuration;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import backtype.storm.security.auth.AuthUtils;
  
  /**
   * client side callback handler.
   */
  public class ClientCallbackHandler implements CallbackHandler {
      private static final String USERNAME = "username";
      private static final String PASSWORD = "password";
      private static final Logger LOG = LoggerFactory.getLogger(ClientCallbackHandler.class);
      private String _username = null;
      private String _password = null;
  
      /**
       * Constructor based on a JAAS configuration
       * 
       * For digest, you should have a pair of user name and password defined.
       * 
       * @param configuration
       * @throws IOException
       */
      public ClientCallbackHandler(Configuration configuration) throws IOException {
          if (configuration == null)
              return;
          AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT);
          if (configurationEntries == null) {
              String errorMessage = "Could not find a '" + AuthUtils.LOGIN_CONTEXT_CLIENT + "' entry in this configuration: Client cannot start.";
              throw new IOException(errorMessage);
          }
  
          _password = "";
          for (AppConfigurationEntry entry : configurationEntries) {
              if (entry.getOptions().get(USERNAME) != null) {
                  _username = (String) entry.getOptions().get(USERNAME);
              }
              if (entry.getOptions().get(PASSWORD) != null) {
                  _password = (String) entry.getOptions().get(PASSWORD);
              }
          }
      }
  
      /**
       * This method is invoked by SASL for authentication challenges
       * 
       * @param callbacks a collection of challenge callbacks
       */
      public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
          for (Callback c : callbacks) {
              if (c instanceof NameCallback) {
                  LOG.debug("name callback");
                  NameCallback nc = (NameCallback) c;
                  nc.setName(_username);
              } else if (c instanceof PasswordCallback) {
                  LOG.debug("password callback");
                  PasswordCallback pc = (PasswordCallback) c;
                  if (_password != null) {
                      pc.setPassword(_password.toCharArray());
                  }
              } else if (c instanceof AuthorizeCallback) {
                  LOG.debug("authorization callback");
                  AuthorizeCallback ac = (AuthorizeCallback) c;
                  String authid = ac.getAuthenticationID();
                  String authzid = ac.getAuthorizationID();
                  if (authid.equals(authzid)) {
                      ac.setAuthorized(true);
                  } else {
                      ac.setAuthorized(false);
                  }
                  if (ac.isAuthorized()) {
                      ac.setAuthorizedID(authzid);
                  }
              } else if (c instanceof RealmCallback) {
                  RealmCallback rc = (RealmCallback) c;
                  ((RealmCallback) c).setText(rc.getDefaultText());
              } else {
                  throw new UnsupportedCallbackException(c);
              }
          }
      }
  }
  