All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.iiop.security.GSSUPToken Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright 2018-2022 Payara Foundation and/or its affiliates
// Payara Foundation and/or its affiliates elects to include this software in this distribution under the GPL Version 2 license
package com.sun.enterprise.iiop.security;

/**
 * GSSUPToken class creates a mechanism specific gssapi token for
 * the username, password mechanism
 * @author Nithya Subramanian
 */

import com.sun.corba.ee.org.omg.CSIIOP.CompoundSecMech;
import com.sun.corba.ee.org.omg.GSSUP.InitialContextToken;
import com.sun.corba.ee.org.omg.GSSUP.InitialContextTokenHelper;
import com.sun.enterprise.security.auth.login.common.PasswordCredential;
import com.sun.enterprise.util.Utility;
import com.sun.logging.LogDomains;
import org.ietf.jgss.GSSException;
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.IOP.Codec;

import java.util.StringTokenizer;
import java.util.logging.Level;

/**
 * GSSUPToken Represents the on the wire username/password credential on the client side and the
 * server side.
 *
 * @author Sekhar Vajjhala
 * @author Harpreet Singh
 */

public class GSSUPToken {
    private static java.util.logging.Logger _logger = null;

    static {
        _logger = LogDomains.getLogger(GSSUPToken.class, LogDomains.SECURITY_LOGGER);
    }
    // START OF IASRI 4825735.
    // to allow for usernames of the type [email protected]
    // Will be represented as user\\@foobar.com@domain
    public static final String DELIMITER_REGEXP = "\\@";
    // backslash for regexp is denoted as \\
    public static final String ESCAPE_CHAR_REGEXP = "\\\\\\@";
    public static final String ESCAPE_CHAR = "\\";
    // START OF IASRI 4825735

    public static final String DELIMITER = "@";
    public static final String DEFAULT_REALM_NAME = "default";

    /**
     * cdr_encoded_token is the GSSAPI mechanism specific token for the user, password mechanism. The
     * mechanism specific token is stored in the CDR encoded form.
     */
    private byte[] cdr_encoded_token = {};

    /* PasswordCredential that contains the username, password and realm */
    PasswordCredential pwdcred = null;

    /**
     * Constructs mechanism token from a password credential, called from the client side interceptors
     *
     * @param orb the ORB
     * @param codec the codec for translation
     * @param pwdcred the Password credential, populated with username/password and the realm name
     * @return GSSUPToken instance of the GSSUPToken class.
     * @since 1.4
     */
    public static GSSUPToken getClientSideInstance(ORB orb, Codec codec, PasswordCredential pwdcred, CompoundSecMech mech) {
        return new GSSUPToken(orb, codec, pwdcred, mech);
    }

    /**
     * Creates a GSSUPToken instance on the server side
     *
     * @param orb the orb
     * @param codec the codec
     * @param authok the authtoken received on the wire.
     * @throws SecurityMechanismException if a name/value pair is not found in the authtok
     * @since 1.4
     */
    public static GSSUPToken getServerSideInstance(ORB orb, Codec codec, byte[] authtok) throws SecurityMechanismException {
        return new GSSUPToken(orb, codec, authtok);
    }

    /**
     * Constructor used to construct a mechansim token from a PasswordCredential. This is used by a
     * context initiator. This is called on the Client Side
     */
    private GSSUPToken(ORB orb, Codec codec, PasswordCredential pwdcred, CompoundSecMech mech) {
        byte[] name_utf8 = {}; // username in UTF8 format
        byte[] password_utf8 = {}; // password in UTF8 format

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "IIOP: Going to construct a GSSUPToken:");
            _logger.log(Level.FINE, pwdcred.toString());
        }

        try {
            String _name_ = pwdcred.getUser();
            // if username is of type [email protected], realm - foo
            // do the following
            // create user\\@sun.com
            // if username is already of the type user\\@foo, dont do anything
            int index = _name_.indexOf(DELIMITER);
            if (index == -1) {
                // no @ - ignore
            } else { // check if it is already escaped
                int escaped_index = _name_.indexOf(ESCAPE_CHAR);
                if (escaped_index == -1) { // delimiter not escaped, escape it
                    _name_ = _name_.replaceAll(DELIMITER_REGEXP, ESCAPE_CHAR_REGEXP);
                } else { // some are escaped, some may be not
                         // rather than traversing the string and escaping
                         // some that are not escaped
                         // just remove the escape on all escaped delimiters
                         // and then re-escape them
                    _name_ = _name_.replaceAll(ESCAPE_CHAR_REGEXP, DELIMITER_REGEXP);
                    _name_ = _name_.replaceAll(DELIMITER_REGEXP, ESCAPE_CHAR_REGEXP);
                }
            }
            String realm = pwdcred.getRealm();
            // concatenation of name+realm
            if (realm != null) {
                // cannot use StringBuilder, as StringBuilder eats away a \
                _name_ = _name_ + DELIMITER + realm;
            }
            name_utf8 = _name_.getBytes("UTF8");
            // password_utf8 = pwdcred.getPassword().getBytes("UTF8");
            password_utf8 = Utility.convertCharArrayToByteArray(pwdcred.getPassword(), "UTF-8");
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.password_exception", e);
        }

        /*
         * Get the target name from the IOR.
         */
        byte[] target_name = mech.as_context_mech.target_name;

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("Username (UTF8) " + GSSUtils.dumpHex(name_utf8));
            // _logger.fine("Password (UTF8) " + GSSUtils.dumpHex(password_utf8));
            _logger.fine("Password (UTF8) " + "########");
            _logger.fine("Targetname      " + GSSUtils.dumpHex(target_name));
        }

        /* Create an InitialContextToken */
        InitialContextToken inctxToken = new InitialContextToken(name_utf8, password_utf8, target_name);

        /* Generate a CDR encoding */
        Any a = orb.create_any();
        InitialContextTokenHelper.insert(a, inctxToken);

        try {
            cdr_encoded_token = codec.encode_value(a);
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.encode_exception", e);
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "IIOP:Mech specific token length (CDR encoded) = " + cdr_encoded_token.length);
        }
    }

    /*
     * Constructor used to construct a mechansim token from a CDR encoded mechanism specific token. This
     * is used by a context acceptor. This is called on the server side.
     */

    private GSSUPToken(ORB orb, Codec codec, byte[] authtok) throws SecurityMechanismException {
        byte[] name_utf8 = null; // username in UTF8 format
        byte[] password_utf8 = null; // password in UTF8 format
        byte[] target_name = null; // target name
        String username = "";
        // String userpwd = "";
        char[] userpwd = null;
        String realm = "";
        byte[] encoded_token = null;

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "IIOP:Going to construct a GSSUPToken:");
            _logger.log(Level.FINE, "IIOP:Getting CDR encoded GSSUP mechanism token from client authentication token");
        }
        /* get CDR encoded mechanism specific token */
        encoded_token = GSSUtils.getMechToken(GSSUtils.GSSUP_MECH_OID, authtok);

        /* create a GSSUPToken from the authentication token */
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "CDR encoded mech specific token length = " + encoded_token.length);
        }
        /* Decode the cdr encoded token */
        Any a = orb.create_any();

        try {
            a = codec.decode_value(encoded_token, InitialContextTokenHelper.type());
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.decode_exception", e);
        }

        InitialContextToken inctxToken = InitialContextTokenHelper.extract(a);

        /* get UTF8 encodings from initial context token */
        password_utf8 = inctxToken.password;
        name_utf8 = inctxToken.username;
        target_name = inctxToken.target_name;

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("IIOP:Username (UTF8) " + GSSUtils.dumpHex(name_utf8));
            // _logger.fine("IIOP:Password (UTF8) " + GSSUtils.dumpHex(password_utf8));
            _logger.fine("IIOP:Password (UTF8) " + "########");
            _logger.fine("IIOP:Targetname      " + GSSUtils.dumpHex(target_name));
        }
        /* Construct a PasswordCredential */
        try {
            username = new String(name_utf8, "UTF8");
            // userpwd = new String(password_utf8, "UTF8");
            userpwd = Utility.convertByteArrayToCharArray(password_utf8, "UTF-8");
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.user_password_exception", e);
        }

        /**
         * decode the username and realm as specified by CSIV2
         */
        String name;
        int index = username.indexOf(DELIMITER);
        int esc_index = username.indexOf(ESCAPE_CHAR);
        if (index == -1) {
            name = username;
        } else if (index == 0 || esc_index == 0) {
            // username is of the form "@realm" or
            // \\@realm or starts with a escape character
            throw new SecurityMechanismException("No name_value in username");
        } else if (esc_index != -1) {
            // START IASRI 4825735 - Changed from 7.0 UR1 to take
            // care of realm-per-app features
            // username\\@sun.com@realm type
            if (esc_index + 2 >= username.length()) {
                // string ends at username\\@ - nothing follows
                name = username.replaceAll(ESCAPE_CHAR_REGEXP, DELIMITER);
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "IIOP:No Realm specified, " + " creating a default realm for login");
                }
                realm = DEFAULT_REALM_NAME;
            } else {
                // locate the second @ token
                // index+2 starts from the first @ sign and thus
                // returns the index of the first @ sign
                // index +3 skips this @ and gives the index of second @
                int second_at_index = username.indexOf(DELIMITER, esc_index + 3);
                if (second_at_index == -1) {
                    // user\\@foobar.com - no realm specified
                    name = username.replaceAll(ESCAPE_CHAR_REGEXP, DELIMITER);

                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.log(Level.FINE, "IIOP:No Realm specified, " + " creating a default realm for login");
                    }
                    realm = DEFAULT_REALM_NAME;
                } else {
                    name = username.substring(0, second_at_index);
                    name = name.replaceAll(ESCAPE_CHAR_REGEXP, DELIMITER);
                    realm = username.substring(second_at_index + 1);
                    if (realm == null || realm.isEmpty()) {
                        // user\\@foo.com@ type
                        if (_logger.isLoggable(Level.FINE)) {
                            _logger.log(Level.FINE, "IIOP:No Realm specified, " + " creating a default realm for login");
                        }
                        realm = DEFAULT_REALM_NAME;
                    }
                }
            }
            // End IASRI 4825735 - Changed from 7.0 UR1
        } else {
            // parse the name and realm tokens
            StringTokenizer strtok = new StringTokenizer(username, DELIMITER);
            name = strtok.nextToken();
            // this checking is neccessary if the username="name@"
            if (strtok.hasMoreTokens()) {
                realm = strtok.nextToken();
                // for realm-per-app
                // if ( !realm.equals("default") )
                // throw new SecurityMechanismException("Unknown realm");
                if (realm.isEmpty()) {
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.log(Level.FINE, "IIOP:No Realm specified, " + " creating a default realm for login");
                    }
                    realm = DEFAULT_REALM_NAME;
                }
            }
        }
        String targetNameRealm = null;
        try {
            if (target_name != null && target_name.length != 0) {
                targetNameRealm = new String(GSSUtils.importName(GSSUtils.GSSUP_MECH_OID, target_name));
            }
        } catch (GSSException ex) {
            _logger.log(Level.FINE, null, ex);
        }
        if (targetNameRealm != null && !DEFAULT_REALM_NAME.equals(targetNameRealm)) {
            realm = targetNameRealm;
        }
        pwdcred = new PasswordCredential(name, userpwd, realm, target_name);
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, pwdcred.toString());
        }
    }

    /**
     * Returns the GSSToken for the GSSUPToken name that conforms to the GSSUP Mechanism id
     *
     * @return byte[] the byte array representation of the GSSToken
     */
    byte[] getGSSToken() throws GSSException {
        if (_logger.isLoggable(Level.FINER)) {
            _logger.log(Level.FINER, "IIOP:GSSUP mech token : " + GSSUtils.dumpHex(cdr_encoded_token));
        }
        /* construct a GSSAPI token ( hdr + mechanism token ) */
        byte[] gsstoken = GSSUtils.createMechIndToken(GSSUtils.GSSUP_MECH_OID, cdr_encoded_token);
        if (_logger.isLoggable(Level.FINER)) {
            _logger.log(Level.FINER, "IIOP:GSSUP token length : " + gsstoken.length);
            _logger.log(Level.FINER, "IIOP:GSSUP token: " + GSSUtils.dumpHex(gsstoken));
        }
        return gsstoken;
    }

    /**
     * @return PasswordCredential the PasswordCredential object that has the username and password. This
     * is called from the server side interceptor
     */
    PasswordCredential getPwdcred() {
        return pwdcred;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy