org.rhq.enterprise.server.naming.NamingHack.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.enterprise.server.naming.NamingHack.java

Source

/*
 * RHQ Management Platform
 * Copyright 2012, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.rhq.enterprise.server.naming;

import java.lang.reflect.Field;
import java.util.Hashtable;

import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;
import javax.naming.spi.NamingManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Lukas Krejci
 */
public class NamingHack {

    private static final Log LOG = LogFactory.getLog(NamingHack.class);

    //in case this method is called multiple times, which can happen during the tests,
    //remember the builder encountered the first time...
    private static InitialContextFactoryBuilder originalBuilder;

    public static void bruteForceInitialContextFactoryBuilder() {
        LOG.info("Modifying the naming subsystem to enable secure execution of scripts inside the server...");

        //it is important to synchronize on the NamingManager class because the get/setInitialContextFactoryBuilder
        //methods in that class are static synchronized. By holding the lock on the NamingManager class we prevent
        //any other thread to check for the initial context factory builder (and therefore de-facto do any JNDI lookup).
        synchronized (NamingManager.class) {

            if (NamingManager.hasInitialContextFactoryBuilder()) {
                //if anyone ever changes the implementation of the NamingManager, we will break here...
                //but as of now, we have no other option but to do this and wait for 
                //https://issues.jboss.org/browse/AS7-6109 to be resolved and incorporated into our underlying container

                try {
                    Field f = NamingManager.class.getDeclaredField("initctx_factory_builder");
                    f.setAccessible(true);

                    if (originalBuilder == null) {
                        originalBuilder = (InitialContextFactoryBuilder) f.get(null);
                    }

                    f.set(null, null);
                } catch (Exception e) {
                    LOG.error(
                            "Failed to install a custom initial context factory builder. RHQ installation is unsecure!",
                            e);

                    return;
                }
            }

            try {
                InitialContextFactory defaultFactory = null;
                if (originalBuilder != null) {
                    defaultFactory = originalBuilder.createInitialContextFactory(new Hashtable<String, String>());
                }

                NamingManager.setInitialContextFactoryBuilder(
                        new AccessCheckingInitialContextFactoryBuilder(defaultFactory, originalBuilder == null));
            } catch (Exception e) {
                LOG.error(
                        "Failed to install a custom initial context factory builder. RHQ installation is unsecure!",
                        e);

                if (originalBuilder != null) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Trying to restore the original initial context factory builder: "
                                + originalBuilder);
                    }

                    try {
                        NamingManager.setInitialContextFactoryBuilder(originalBuilder);
                    } catch (Exception e2) {
                        LOG.error(
                                "Failed to restore the original initial context factory builder. The JNDI lookup may"
                                        + " not function properly from this point on...",
                                e2);
                    }
                }
            }
        }
    }

}