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    }