001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.security.jaas.server;
018
019 import javax.security.auth.callback.Callback;
020 import javax.security.auth.callback.CallbackHandler;
021 import javax.security.auth.callback.UnsupportedCallbackException;
022
023 /**
024 * This callback handler separates the process of obtaining callbacks from
025 * the user from the process of providing the user's values to the login
026 * module. This means the JaasLoginService can figure out what callbacks
027 * the module wants and prompt the user in advance, and then turn around
028 * and pass those values to the login module, instead of actually prompting
029 * the user at the mercy of the login module.
030 *
031 * @version $Rev: 487175 $ $Date: 2006-12-14 03:10:31 -0800 (Thu, 14 Dec 2006) $
032 */
033 public class DecouplingCallbackHandler implements CallbackHandler {
034 private Callback[] source;
035 private boolean exploring = true;
036
037 public DecouplingCallbackHandler() {
038 }
039
040 public void handle(Callback[] callbacks) throws IllegalArgumentException, UnsupportedCallbackException {
041 if (exploring) {
042 source = callbacks;
043 throw new UnsupportedCallbackException(callbacks != null && callbacks.length > 0 ? callbacks[0] : null, "DO NOT PROCEED WITH THIS LOGIN");
044 } else {
045 if(callbacks.length != source.length) {
046 throw new IllegalArgumentException("Mismatched callbacks");
047 }
048 for (int i = 0; i < callbacks.length; i++) {
049 callbacks[i] = source[i];
050 }
051 }
052 }
053
054 /**
055 * Within the same VM, the client just populates the callbacks directly
056 * into the array held by this object. However, remote clients will
057 * serialize their responses, so they need to be manually set back on this
058 * object to take effect.
059 *
060 * @param callbacks The callbacks populated by the client
061 */
062 public void setClientResponse(Callback[] callbacks) throws IllegalArgumentException {
063 if(source == null && callbacks == null) {
064 return; // i.e. The Kerberos LM doesn't need callbacks
065 }
066 if(callbacks.length != source.length) {
067 throw new IllegalArgumentException("Mismatched callbacks");
068 }
069 for (int i = 0; i < callbacks.length; i++) {
070 source[i] = callbacks[i];
071 }
072 }
073
074
075 /**
076 * While we're exploring, we'll discover new callbacks that the server
077 * login module wants. While not exploring, we'll actually set
078 * values for the server callbacks.
079 */
080 public void setExploring() {
081 exploring = true;
082 source = null;
083 }
084
085 /**
086 * Indicates that the exploring phase is over.
087 */
088 public Callback[] finalizeCallbackList() {
089 exploring = false;
090 return source;
091 }
092 }