Package org.wso2.carbon.apacheds.impl

Source Code of org.wso2.carbon.apacheds.impl.ApacheLDAPServer

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.apacheds.impl;

import org.apache.axiom.om.util.Base64;
import org.apache.directory.server.core.CoreSession;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.LdapPrincipal;
import org.apache.directory.server.core.factory.DirectoryServiceFactory;
import org.apache.directory.server.core.interceptor.Interceptor;
import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
import org.apache.directory.server.ldap.LdapServer;
import org.apache.directory.server.ldap.handlers.bind.MechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.cramMD5.CramMd5MechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.digestMD5.DigestMd5MechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.gssapi.GssapiMechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.ntlm.NtlmMechanismHandler;
import org.apache.directory.server.ldap.handlers.bind.plain.PlainMechanismHandler;
import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
import org.apache.directory.server.ldap.handlers.extended.StoredProcedureExtendedOperationHandler;
import org.apache.directory.server.protocol.shared.transport.TcpTransport;
import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
import org.apache.directory.shared.ldap.entry.DefaultServerAttribute;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
import org.apache.directory.shared.ldap.entry.ServerModification;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.message.ModifyDnRequestImpl;
import org.apache.directory.shared.ldap.message.internal.InternalModifyDnRequest;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.apacheds.LDAPConfiguration;
import org.wso2.carbon.apacheds.LDAPServer;
import org.wso2.carbon.apacheds.PartitionManager;
import org.wso2.carbon.apacheds.exception.DirectoryServerException;

import javax.naming.NamingException;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* An implementation of LDAP server. This wraps apacheds implementation and provides an
* abstract interface to operate on directory server.
*/
@SuppressWarnings({"UnusedDeclaration"})
public class ApacheLDAPServer implements LDAPServer {

    private DirectoryService service;

    private LdapServer ldapServer;

    private PartitionManager partitionManager;

    private LDAPConfiguration ldapConfigurations;

    private static final Logger logger = LoggerFactory.getLogger(ApacheLDAPServer.class);

    public void init(LDAPConfiguration configurations)
            throws DirectoryServerException {

        if (configurations == null) {
            logger.error("LDAP server initialization failed. " +
                         "LDAP server configuration is invalid.");
            throw new DirectoryServerException("Cannot initialize LDAP server. " +
                                               "Configuration is null");
        }


        this.ldapConfigurations = configurations;

        try {

            initializeDefaultDirectoryService();
            initializeLDAPServer();

            partitionManager = new ApacheDirectoryPartitionManager(
                    this.service, this.ldapConfigurations.getWorkingDirectory());

        } catch (Exception e) {
            logger.error("LDAP server initialization failed.", e);
            throw new DirectoryServerException("Error initializing ApacheLDAPServer. ", e);
        }

    }

    public DirectoryService getService() {
        return service;
    }

    public void setService(DirectoryService service) {
        this.service = service;
    }

    public void start()
            throws DirectoryServerException {

        try {
            this.service.startup();
            this.ldapServer.start();
            logger.info("LDAP server started.");
        } catch (Exception e) {

            logger.error("Error starting LDAP server.", e);
            throw new DirectoryServerException("Can not start the server ", e);
        }
    }

    public void stop()
            throws DirectoryServerException {

        try {

            this.ldapServer.stop();
            this.service.shutdown();
            logger.info("LDAP server stopped.");
        } catch (Exception e) {

            logger.error("Error stopping LDAP server.", e);
            throw new DirectoryServerException("Can not start the server ", e);
        }
    }

    public PartitionManager getPartitionManager()
            throws DirectoryServerException {

        return this.partitionManager;
    }

    protected void initializeDefaultDirectoryService()
            throws DirectoryServerException {
        try {

            DirectoryServiceFactory factory = CarbonDirectoryServiceFactory.DEFAULT;
            this.service = factory.getDirectoryService();

            configureDirectoryService();

            factory.init(this.ldapConfigurations.getInstanceId());

        } catch (Exception e) {
            throw new DirectoryServerException("Can not start the Default apacheds service ", e);
        }
    }

    private AttributeType getAttributeType(String attributeName)
            throws DirectoryServerException {
        if (this.service != null) {
            SchemaManager schemaManager = this.service.getSchemaManager();
            if (schemaManager != null) {
                AttributeTypeRegistry registry = schemaManager.getAttributeTypeRegistry();
                if (registry != null) {
                    try {
                        String oid = registry.getOidByName(attributeName);
                        return registry.lookup(oid);
                    } catch (LdapException e) {
                        String msg = "An error occurred while querying attribute " + attributeName +
                                     " from registry.";
                        logger.error(msg, e);
                        throw new DirectoryServerException(msg, e);
                    }
                } else {
                    String msg = "Could not get attribute registry.";
                    logger.error(msg);
                    throw new DirectoryServerException(msg);

                }

            } else {
                String msg = "Cannot access schema manager. Directory server may not have started.";
                logger.error(msg);
                throw new DirectoryServerException(msg);

            }
        } else {
            String msg = "The directory service is null. LDAP server might not have started.";
            logger.error(msg);
            throw new DirectoryServerException(msg);

        }
    }

    private void throwException(String message, Throwable e)
            throws DirectoryServerException {
        if (e == null) {
            logger.error(message);
            throw new DirectoryServerException(message);
        } else {
            logger.error(message, e);
            throw new DirectoryServerException(message, e);
        }
    }

    public String getConnectionDomainName()
            throws DirectoryServerException {

        LdapPrincipal adminPrinciple = getAdminPrinciple();
        return adminPrinciple.getClonedName().getName();
    }

    private LdapPrincipal getAdminPrinciple()
            throws DirectoryServerException {

        if (this.service != null) {
            CoreSession adminSession;
            try {
                adminSession = this.service.getAdminSession();
            } catch (Exception e) {
                String msg = "An error occurred while retraining admin session.";
                logger.error(msg, e);
                throw new DirectoryServerException(msg, e);
            }
            if (adminSession != null) {
                LdapPrincipal adminPrincipal = adminSession.getAuthenticatedPrincipal();
                if (adminPrincipal != null) {
                    return adminPrincipal;
                } else {
                    String msg = "Could not retrieve admin principle. Failed changing connection " +
                                 "user password.";
                    logger.error(msg);
                    throw new DirectoryServerException(msg);
                }
            } else {
                String msg = "Directory admin session is null. The LDAP server may not have " +
                             "started yet.";
                logger.error(msg);
                throw new DirectoryServerException(msg);
            }
        } else {
            String msg = "Directory service is null. The LDAP server may not have started yet.";
            logger.error(msg);
            throw new DirectoryServerException(msg);
        }

    }

    public void changeConnectionUserPassword(String password)
            throws DirectoryServerException {

        if (this.service != null) {
            CoreSession adminSession;
            try {
                adminSession = this.service.getAdminSession();
            } catch (Exception e) {
                String msg = "An error occurred while retraining admin session.";
                logger.error(msg, e);
                throw new DirectoryServerException(msg, e);
            }
            if (adminSession != null) {
                LdapPrincipal adminPrincipal = adminSession.getAuthenticatedPrincipal();
                if (adminPrincipal != null) {

                    String passwordToStore = "{" + ConfigurationConstants.ADMIN_PASSWORD_ALGORITHM +
                                             "}";

                    MessageDigest messageDigest;
                    try {
                        messageDigest = MessageDigest.getInstance(
                                ConfigurationConstants.ADMIN_PASSWORD_ALGORITHM);
                    } catch (NoSuchAlgorithmException e) {
                        throw new DirectoryServerException(
                                "Could not find digest algorithm - " +
                                ConfigurationConstants.ADMIN_PASSWORD_ALGORITHM);
                    }
                    messageDigest.update(password.getBytes());
                    byte[] bytes = messageDigest.digest();
                    String hash = Base64.encode(bytes);
                    passwordToStore = passwordToStore + hash;

                    adminPrincipal.setUserPassword(passwordToStore.getBytes());

                    InternalModifyDnRequest request = new ModifyDnRequestImpl(0);

                    EntryAttribute passwordAttribute = new DefaultServerAttribute(
                            getAttributeType("userPassword"));
                    passwordAttribute.add(passwordToStore.getBytes());

                    ServerModification serverModification =
                            new ServerModification(ModificationOperation.REPLACE_ATTRIBUTE,
                                                   passwordAttribute);

                    List<Modification> modifiedList = new ArrayList<Modification>();
                    modifiedList.add(serverModification);

                    try {
                        adminSession.modify(adminPrincipal.getClonedName(), modifiedList);
                    } catch (Exception e) {
                        String msg = "Failed changing connection user password.";
                        logger.error(msg, e);
                        throw new DirectoryServerException(msg, e);
                    }

                } else {
                    String msg = "Could not retrieve admin principle. Failed changing connection " +
                                 "user password.";
                    logger.error(msg);
                    throw new DirectoryServerException(msg);
                }
            } else {
                String msg = "Directory admin session is null. The LDAP server may not have " +
                             "started yet.";
                logger.error(msg);
                throw new DirectoryServerException(msg);
            }
        } else {
            String msg = "Directory service is null. The LDAP server may not have started yet.";
            logger.error(msg);
            throw new DirectoryServerException(msg);
        }

    }

    private void configureDirectoryService()
            throws NamingException, DirectoryServerException {

        if (null == this.ldapConfigurations) {
            throw new DirectoryServerException("Directory service is not initialized.");
        }

        System.setProperty("workingDirectory", this.ldapConfigurations.getWorkingDirectory());

        this.service.setShutdownHookEnabled(false);

        this.service.setInstanceId(this.ldapConfigurations.getInstanceId());
        this.service.setAllowAnonymousAccess(this.ldapConfigurations.isAllowAnonymousAccess());
        this.service.setAccessControlEnabled(this.ldapConfigurations.isAccessControlOn());
        this.service.setDenormalizeOpAttrsEnabled(
                this.ldapConfigurations.isDeNormalizedAttributesEnabled());
        this.service.setMaxPDUSize(this.ldapConfigurations.getMaxPDUSize());

        this.service.getChangeLog().setEnabled(this.ldapConfigurations.isChangeLogEnabled());

        // Add interceptors
        List<Interceptor> list = this.service.getInterceptors();
        list.add(new KeyDerivationInterceptor());
        this.service.setInterceptors(list);

    }

    protected void initializeLDAPServer()
            throws DirectoryServerException {

        if (null == this.service || null == this.ldapConfigurations) {
            throw new DirectoryServerException(
                    "The default apacheds service is not initialized. " +
                    "Make sure apacheds service is initialized first.");
        }

        this.ldapServer = new LdapServer();

        this.ldapServer.setTransports(new TcpTransport(this.ldapConfigurations.getLdapPort()));

        // set server initial properties
        this.ldapServer.setAllowAnonymousAccess(false);
        this.ldapServer.setMaxTimeLimit(this.ldapConfigurations.getMaxTimeLimit());
        this.ldapServer.setMaxSizeLimit(this.ldapConfigurations.getMaxSizeLimit());
        this.ldapServer.setSaslHost(this.ldapConfigurations.getSaslHostName());
        this.ldapServer.setSaslPrincipal(this.ldapConfigurations.getSaslPrincipalName());

        // add the apacheds service
        this.ldapServer.setDirectoryService(this.service);

        setupSaslMechanisms();

        try {
            this.ldapServer.addExtendedOperationHandler(new StartTlsHandler());
            this.ldapServer.addExtendedOperationHandler(
                    new StoredProcedureExtendedOperationHandler());
        } catch (Exception e) {
            throw new DirectoryServerException("can not add the extension handlers ", e);
        }
    }

    private void setupSaslMechanisms() {
        Map<String, MechanismHandler> mechanismHandlerMap = new HashMap<String, MechanismHandler>();

        mechanismHandlerMap.put(SupportedSaslMechanisms.PLAIN, new PlainMechanismHandler());

        CramMd5MechanismHandler cramMd5MechanismHandler = new CramMd5MechanismHandler();
        mechanismHandlerMap.put(SupportedSaslMechanisms.CRAM_MD5, cramMd5MechanismHandler);

        DigestMd5MechanismHandler digestMd5MechanismHandler = new DigestMd5MechanismHandler();
        mechanismHandlerMap.put(SupportedSaslMechanisms.DIGEST_MD5, digestMd5MechanismHandler);

        GssapiMechanismHandler gssapiMechanismHandler = new GssapiMechanismHandler();
        mechanismHandlerMap.put(SupportedSaslMechanisms.GSSAPI, gssapiMechanismHandler);

        NtlmMechanismHandler ntlmMechanismHandler = new NtlmMechanismHandler();

        mechanismHandlerMap.put(SupportedSaslMechanisms.NTLM, ntlmMechanismHandler);
        mechanismHandlerMap.put(SupportedSaslMechanisms.GSS_SPNEGO, ntlmMechanismHandler);

        this.ldapServer.setSaslMechanismHandlers(mechanismHandlerMap);
    }
}
TOP

Related Classes of org.wso2.carbon.apacheds.impl.ApacheLDAPServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.