160 lines · 5.8 KB · Java
RawDownload
/* * Copyright (c) 1999, 2006, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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);        }    }}