/*
 * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.security.sasl;

import javax.security.sasl.*;
import com.sun.security.sasl.util.PolicyUtils;

import java.util.Map;
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;

/**
  * Client factory for EXTERNAL, CRAM-MD5, PLAIN.
  *
  * Requires the following callbacks to be satisfied by callback handler
  * when using CRAM-MD5 or PLAIN.
  * - NameCallback (to get username)
  * - PasswordCallback (to get password)
  *
  * @author Rosanna Lee
  */
final public class ClientFactoryImpl implements SaslClientFactory {
    private static final String myMechs[] = {
        "EXTERNAL",
        "CRAM-MD5",
        "PLAIN",
    };

    private static final int mechPolicies[] = {
        // %%% RL: Policies should actually depend on the external channel
        PolicyUtils.NOPLAINTEXT|PolicyUtils.NOACTIVE|PolicyUtils.NODICTIONARY,
        PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS,    // CRAM-MD5
        PolicyUtils.NOANONYMOUS,                            // PLAIN
    };

    private static final int EXTERNAL = 0;
    private static final int CRAMMD5 = 1;
    private static final int PLAIN = 2;

    public ClientFactoryImpl() {
    }

    public SaslClient createSaslClient(String[] mechs,
        String authorizationId,
        String protocol,
        String serverName,
        Map<String,?> props,
        CallbackHandler cbh) throws SaslException {

            for (int i = 0; i < mechs.length; i++) {
                if (mechs[i].equals(myMechs[EXTERNAL])
                    && PolicyUtils.checkPolicy(mechPolicies[EXTERNAL], props)) {
                    return new ExternalClient(authorizationId);

                } else if (mechs[i].equals(myMechs[CRAMMD5])
                    && PolicyUtils.checkPolicy(mechPolicies[CRAMMD5], props)) {

                    Object[] uinfo = getUserInfo("CRAM-MD5", authorizationId, cbh);

                    // Callee responsible for clearing bytepw
                    return new CramMD5Client((String) uinfo[0],
                        (byte []) uinfo[1]);

                } else if (mechs[i].equals(myMechs[PLAIN])
                    && PolicyUtils.checkPolicy(mechPolicies[PLAIN], props)) {

                    Object[] uinfo = getUserInfo("PLAIN", authorizationId, cbh);

                    // Callee responsible for clearing bytepw
                    return new PlainClient(authorizationId,
                        (String) uinfo[0], (byte []) uinfo[1]);
                }
            }
            return null;
    };

    public String[] getMechanismNames(Map<String,?> props) {
        return PolicyUtils.filterMechs(myMechs, mechPolicies, props);
    }

    /**
     * Gets the authentication id and password. The
     * password is converted to bytes using UTF-8 and stored in bytepw.
     * The authentication id is stored in authId.
     *
     * @param prefix The non-null prefix to use for the prompt (e.g., mechanism
     *  name)
     * @param authorizationId The possibly null authorization id. This is used
     * as a default for the NameCallback. If null, it is not used in prompt.
     * @param cbh The non-null callback handler to use.
     * @return an {authid, passwd} pair
     */
    private Object[] getUserInfo(String prefix, String authorizationId,
        CallbackHandler cbh) throws SaslException {
        if (cbh == null) {
            throw new SaslException(
                "Callback handler to get username/password required");
        }
        try {
            String userPrompt = prefix + " authentication id: ";
            String passwdPrompt = prefix + " password: ";

            NameCallback ncb = authorizationId == null?
                new NameCallback(userPrompt) :
                new NameCallback(userPrompt, authorizationId);

            PasswordCallback pcb = new PasswordCallback(passwdPrompt, false);

            cbh.handle(new Callback[]{ncb,pcb});

            char[] pw = pcb.getPassword();

            byte[] bytepw;
            String authId;

            if (pw != null) {
                bytepw = new String(pw).getBytes("UTF8");
                pcb.clearPassword();
            } else {
                bytepw = null;
            }

            authId = ncb.getName();

            return new Object[]{authId, bytepw};

        } catch (IOException e) {
            throw new SaslException("Cannot get password", e);
        } catch (UnsupportedCallbackException e) {
            throw new SaslException("Cannot get userid/password", e);
        }
    }
}
