org.jboss.test.kerberos.KerberosSetup.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.test.kerberos.KerberosSetup.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, Red Hat, Inc., 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 is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.test.kerberos;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.directory.api.ldap.model.constants.SupportedSaslMechanisms;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.ldap.model.ldif.LdifReader;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.server.annotations.CreateKdcServer;
import org.apache.directory.server.annotations.CreateLdapServer;
import org.apache.directory.server.annotations.CreateTransport;
import org.apache.directory.server.annotations.SaslMechanism;
import org.apache.directory.server.core.annotations.AnnotationUtils;
import org.apache.directory.server.core.annotations.ContextEntry;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.annotations.CreateIndex;
import org.apache.directory.server.core.annotations.CreatePartition;
import org.apache.directory.server.core.api.DirectoryService;
import org.apache.directory.server.core.factory.DSAnnotationProcessor;
import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
import org.apache.directory.server.factory.ServerAnnotationProcessor;
import org.apache.directory.server.kerberos.kdc.KdcServer;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.ldap.handlers.sasl.cramMD5.CramMd5MechanismHandler;
import org.apache.directory.server.ldap.handlers.sasl.digestMD5.DigestMd5MechanismHandler;
import org.apache.directory.server.ldap.handlers.sasl.gssapi.GssapiMechanismHandler;
import org.apache.directory.server.ldap.handlers.sasl.ntlm.NtlmMechanismHandler;
import org.apache.directory.server.ldap.handlers.sasl.plain.PlainMechanismHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Kerberos configuration and control main class.
 * 
 * @author Josef Cacek
 */
//@formatter:off
@CreateDS(name = "JBossDS", partitions = {
        @CreatePartition(name = "jboss", suffix = "dc=jboss,dc=org", contextEntry = @ContextEntry(entryLdif = "dn: dc=jboss,dc=org\n"
                + "dc: jboss\n" + "objectClass: top\n" + "objectClass: domain\n\n"), indexes = {
                        @CreateIndex(attribute = "objectClass"), @CreateIndex(attribute = "dc"),
                        @CreateIndex(attribute = "ou") }) }, additionalInterceptors = {
                                KeyDerivationInterceptor.class })
@CreateLdapServer(transports = {
        @CreateTransport(protocol = "LDAP", port = 10389) }, saslHost = "localhost", saslPrincipal = "ldap/localhost@JBOSS.ORG", saslMechanisms = {
                @SaslMechanism(name = SupportedSaslMechanisms.PLAIN, implClass = PlainMechanismHandler.class),
                @SaslMechanism(name = SupportedSaslMechanisms.CRAM_MD5, implClass = CramMd5MechanismHandler.class),
                @SaslMechanism(name = SupportedSaslMechanisms.DIGEST_MD5, implClass = DigestMd5MechanismHandler.class),
                @SaslMechanism(name = SupportedSaslMechanisms.GSSAPI, implClass = GssapiMechanismHandler.class),
                @SaslMechanism(name = SupportedSaslMechanisms.NTLM, implClass = NtlmMechanismHandler.class),
                @SaslMechanism(name = SupportedSaslMechanisms.GSS_SPNEGO, implClass = NtlmMechanismHandler.class) })
@CreateKdcServer(primaryRealm = "JBOSS.ORG", kdcPrincipal = "krbtgt/JBOSS.ORG@JBOSS.ORG", searchBaseDn = "dc=jboss,dc=org", transports = {
        @CreateTransport(protocol = "UDP", port = 6088) })
//@formatter:on
public class KerberosSetup {
    private static Logger LOGGER = LoggerFactory.getLogger(KerberosSetup.class);

    private static final int SOCKET_TIMEOUT = 2000; // 2 seconds

    private static final String STOP_CMD = "stop";
    private static final int SERVER_PORT = 10959;

    private DirectoryService directoryService;
    private LdapServer ldapServer;
    private KdcServer kdcServer;
    private final String canonicalHost;
    private final String krb5ConfPath;

    // Constructors ----------------------------------------------------------

    public KerberosSetup() {
        canonicalHost = getCannonicalHost(System.getProperty("kerberos.bind.address", "localhost"));
        krb5ConfPath = System.getProperty("kerberos.conf.path", "krb5.conf");
    }

    // Public methods --------------------------------------------------------

    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
        try {
            if (args.length == 1 && STOP_CMD.equals(args[0])) {
                System.out.println("Sending STOP command to Kerberos controll process.");
                SocketAddress sockaddr = new InetSocketAddress(InetAddress.getLocalHost(), SERVER_PORT);
                // Create an unbound socket
                Socket sock = new Socket();
                sock.connect(sockaddr, SOCKET_TIMEOUT);
                BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
                wr.write(STOP_CMD);
                wr.close();
                sock.close();
            } else {
                System.out.println("Starting Kerberos controll process.");
                KerberosSetup ns = new KerberosSetup();
                ns.startKDC(args);
                ns.waitForStop();
                ns.stopKDC();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

    }

    // Protected methods -----------------------------------------------------

    protected void waitForStop() throws Exception {
        final ServerSocket srv = new ServerSocket(SERVER_PORT);
        boolean isStop = false;
        do {
            // Wait for connection from client.
            Socket socket = srv.accept();
            System.out.println("Incomming connection.");
            socket.setSoTimeout(SOCKET_TIMEOUT);
            BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            try {
                isStop = STOP_CMD.equals(rd.readLine());
            } finally {
                rd.close();
            }
            System.out.println("Stop command: " + isStop);
            socket.close();
        } while (!isStop);
        IOUtils.closeQuietly(srv);
    }

    protected void startKDC(final String[] args) throws Exception {
        directoryService = DSAnnotationProcessor.getDirectoryService();
        LOGGER.info("Initializing KDC server with binding to '{}'", canonicalHost);
        final Map<String, String> map = new HashMap<String, String>();
        map.put("hostname", canonicalHost);
        if (args != null && args.length > 0) {
            for (String ldifFile : args) {

                final String ldifContent = StrSubstitutor
                        .replace(FileUtils.readFileToString(new File(ldifFile), "UTF-8"), map);
                LOGGER.debug(ldifContent);
                final SchemaManager schemaManager = directoryService.getSchemaManager();
                try {
                    for (LdifEntry ldifEntry : new LdifReader(IOUtils.toInputStream(ldifContent))) {
                        directoryService.getAdminSession()
                                .add(new DefaultEntry(schemaManager, ldifEntry.getEntry()));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw e;
                }
            }
        }
        LOGGER.info("Generating kerberos configuration file '{}'", krb5ConfPath);
        FileUtils.write(new File(krb5ConfPath), StrSubstitutor
                .replace(IOUtils.toString(getClass().getResourceAsStream("/krb5.conf"), "UTF-8"), map));
        System.out.println("Starting KDC");
        kdcServer = KDCServerAnnotationProcessor.getKdcServer(directoryService, 1024, canonicalHost);
        System.out.println("Starting LDAP server");
        final ManagedCreateLdapServer createLdapServer = new ManagedCreateLdapServer(
                (CreateLdapServer) AnnotationUtils.getInstance(CreateLdapServer.class));
        createLdapServer.setSaslHost(canonicalHost);
        createLdapServer.setSaslPrincipal("ldap/" + canonicalHost + "@JBOSS.ORG");
        fixTransportAddress(createLdapServer, canonicalHost);
        ldapServer = ServerAnnotationProcessor.instantiateLdapServer(createLdapServer, directoryService);
        ldapServer.setSearchBaseDn("dc=jboss,dc=org");
        ldapServer.start();
    }

    protected void stopKDC() throws Exception {
        System.out.println("Stoping LDAP server.");
        ldapServer.stop();
        System.out.println("Stoping Kerberos server.");
        kdcServer.stop();
        System.out.println("Stoping Directory service.");
        directoryService.shutdown();
        System.out.println("Removing Directory service workfiles.");
        FileUtils.deleteDirectory(directoryService.getInstanceLayout().getInstanceDirectory());
    }

    // Private methods -------------------------------------------------------

    /**
     * Returns canonical hostname form of the given host address.
     * 
     * @param host address
     * @return
     */
    private static final String getCannonicalHost(String host) {
        try {
            host = InetAddress.getByName(host).getCanonicalHostName();
        } catch (UnknownHostException e) {
            LOGGER.warn("Unable to get cannonical host name", e);
        }
        return host.toLowerCase(Locale.ENGLISH);
    }

    /**
     * Fixes bind address in the CreateTransport annotation.
     *
     * @param createLdapServer
     */
    private void fixTransportAddress(ManagedCreateLdapServer createLdapServer, String address) {
        final CreateTransport[] createTransports = createLdapServer.transports();
        for (int i = 0; i < createTransports.length; i++) {
            final ManagedCreateTransport mgCreateTransport = new ManagedCreateTransport(createTransports[i]);
            mgCreateTransport.setAddress(address);
            createTransports[i] = mgCreateTransport;
        }
    }
}