/*
 * 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 org.apache.catalina.realm;


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.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.tomcat.util.res.StringManager;

Implementation of the JAAS CallbackHandler interface, used to negotiate delivery of the username and credentials that were specified to our constructor. No interaction with the user is required (or possible).

This CallbackHandler will pre-digest the supplied password, if required by the <Realm> element in server.xml.

At present, JAASCallbackHandler knows how to handle callbacks of type javax.security.auth.callback.NameCallback and javax.security.auth.callback.PasswordCallback.

Author:Craig R. McClanahan, Andrew R. Jaquith
/** * <p>Implementation of the JAAS <code>CallbackHandler</code> interface, * used to negotiate delivery of the username and credentials that were * specified to our constructor. No interaction with the user is required * (or possible).</p> * * <p>This <code>CallbackHandler</code> will pre-digest the supplied * password, if required by the <code>&lt;Realm&gt;</code> element in * <code>server.xml</code>.</p> * <p>At present, <code>JAASCallbackHandler</code> knows how to handle callbacks of * type <code>javax.security.auth.callback.NameCallback</code> and * <code>javax.security.auth.callback.PasswordCallback</code>.</p> * * @author Craig R. McClanahan * @author Andrew R. Jaquith */
public class JAASCallbackHandler implements CallbackHandler { // ------------------------------------------------------------ Constructor
Construct a callback handler configured with the specified values. Note that if the JAASRealm instance specifies digested passwords, the password parameter will be pre-digested here.
Params:
  • realm – Our associated JAASRealm instance
  • username – Username to be authenticated with
  • password – Password to be authenticated with
/** * Construct a callback handler configured with the specified values. * Note that if the <code>JAASRealm</code> instance specifies digested passwords, * the <code>password</code> parameter will be pre-digested here. * * @param realm Our associated JAASRealm instance * @param username Username to be authenticated with * @param password Password to be authenticated with */
public JAASCallbackHandler(JAASRealm realm, String username, String password) { this(realm, username, password, null, null, null, null, null, null, null); }
Construct a callback handler for DIGEST authentication.
Params:
  • realm – Our associated JAASRealm instance
  • username – Username to be authenticated with
  • password – Password to be authenticated with
  • nonce – Server generated nonce
  • nc – Nonce count
  • cnonce – Client generated nonce
  • qop – Quality of protection applied to the message
  • realmName – Realm name
  • md5a2 – Second MD5 digest used to calculate the digest MD5(Method + ":" + uri)
  • authMethod – The authentication method in use
/** * Construct a callback handler for DIGEST authentication. * * @param realm Our associated JAASRealm instance * @param username Username to be authenticated with * @param password Password to be authenticated with * @param nonce Server generated nonce * @param nc Nonce count * @param cnonce Client generated nonce * @param qop Quality of protection applied to the message * @param realmName Realm name * @param md5a2 Second MD5 digest used to calculate the digest * MD5(Method + ":" + uri) * @param authMethod The authentication method in use */
public JAASCallbackHandler(JAASRealm realm, String username, String password, String nonce, String nc, String cnonce, String qop, String realmName, String md5a2, String authMethod) { this.realm = realm; this.username = username; if (password != null && realm.hasMessageDigest()) { this.password = realm.getCredentialHandler().mutate(password); } else { this.password = password; } this.nonce = nonce; this.nc = nc; this.cnonce = cnonce; this.qop = qop; this.realmName = realmName; this.md5a2 = md5a2; this.authMethod = authMethod; } // ----------------------------------------------------- Instance Variables
The string manager for this package.
/** * The string manager for this package. */
protected static final StringManager sm = StringManager.getManager(JAASCallbackHandler.class);
The password to be authenticated with.
/** * The password to be authenticated with. */
protected final String password;
The associated JAASRealm instance.
/** * The associated <code>JAASRealm</code> instance. */
protected final JAASRealm realm;
The username to be authenticated with.
/** * The username to be authenticated with. */
protected final String username;
Server generated nonce.
/** * Server generated nonce. */
protected final String nonce;
Nonce count.
/** * Nonce count. */
protected final String nc;
Client generated nonce.
/** * Client generated nonce. */
protected final String cnonce;
Quality of protection applied to the message.
/** * Quality of protection applied to the message. */
protected final String qop;
Realm name.
/** * Realm name. */
protected final String realmName;
Second MD5 digest.
/** * Second MD5 digest. */
protected final String md5a2;
The authentication method to be used. If null, assume BASIC/FORM.
/** * The authentication method to be used. If null, assume BASIC/FORM. */
protected final String authMethod; // --------------------------------------------------------- Public Methods
Retrieve the information requested in the provided Callbacks. This implementation only recognizes NameCallback, PasswordCallback and TextInputCallback. TextInputCallback is used to pass the various additional parameters required for DIGEST authentication.
Params:
  • callbacks – The set of Callbacks to be processed
Throws:
/** * Retrieve the information requested in the provided <code>Callbacks</code>. * This implementation only recognizes {@link NameCallback}, * {@link PasswordCallback} and {@link TextInputCallback}. * {@link TextInputCallback} is used to pass the various additional * parameters required for DIGEST authentication. * * @param callbacks The set of <code>Callback</code>s to be processed * * @exception IOException if an input/output error occurs * @exception UnsupportedCallbackException if the login method requests * an unsupported callback type */
@Override public void handle(Callback callbacks[]) throws IOException, UnsupportedCallbackException { for (Callback callback : callbacks) { if (callback instanceof NameCallback) { if (realm.getContainer().getLogger().isTraceEnabled()) realm.getContainer().getLogger().trace(sm.getString("jaasCallback.username", username)); ((NameCallback) callback).setName(username); } else if (callback instanceof PasswordCallback) { final char[] passwordcontents; if (password != null) { passwordcontents = password.toCharArray(); } else { passwordcontents = new char[0]; } ((PasswordCallback) callback).setPassword (passwordcontents); } else if (callback instanceof TextInputCallback) { TextInputCallback cb = ((TextInputCallback) callback); if (cb.getPrompt().equals("nonce")) { cb.setText(nonce); } else if (cb.getPrompt().equals("nc")) { cb.setText(nc); } else if (cb.getPrompt().equals("cnonce")) { cb.setText(cnonce); } else if (cb.getPrompt().equals("qop")) { cb.setText(qop); } else if (cb.getPrompt().equals("realmName")) { cb.setText(realmName); } else if (cb.getPrompt().equals("md5a2")) { cb.setText(md5a2); } else if (cb.getPrompt().equals("authMethod")) { cb.setText(authMethod); } else if (cb.getPrompt().equals("catalinaBase")) { cb.setText(realm.getContainer().getCatalinaBase().getAbsolutePath()); } else { throw new UnsupportedCallbackException(callback); } } else { throw new UnsupportedCallbackException(callback); } } } }