*    Copyright 2017 Kaiserpfalz EDV-Service, Roland T. Lichti
 *    Licensed 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 de.kaiserpfalzedv.ocp.groupsync.ldap;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Hashtable;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.validation.constraints.NotNull;

import de.kaiserpfalzedv.ocp.groupsync.ocp.providers.ServerCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

 * @author klenkes {@literal <[email protected]>}
 * @version 1.0.0
 * @since 2017-09-10
public class LdapServer {
    private static final Logger LOG = LoggerFactory.getLogger(LdapServer.class);

    private String ldapServer;

    private String bindDN = null;

    private String bindPassword = null;

    private ServerCredentials serverCredentials;

    private final Hashtable<String, Object> env = new Hashtable<>();

    public LdapServer(@NotNull final ServerCredentials serverCredentials) {
        this.serverCredentials = serverCredentials;

    public void initializeContext() throws NamingException {


        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {

                public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {

                public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
            ctx.init(null, new TrustManager[]{tm}, null);
        } catch (Exception ex) {

    private void createLdapConnectionConfiguration() {
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, bindDN);
        env.put(Context.SECURITY_CREDENTIALS, bindPassword);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldapServer);
        env.put("java.naming.ldap.attributes.binary", "objectSID");

        if (LOG.isTraceEnabled()) {
            env.put("com.sun.jndi.ldap.trace.ber", System.err);

    private void readServerCredentials() {
        if(serverCredentials != null) {
            if ("-".equals(ldapServer)) {
                ldapServer = serverCredentials.getServer();

            if ("-".equals(bindDN)) {
                bindDN = serverCredentials.getUser();

            if ("-".equals(bindPassword)) {
                bindPassword = serverCredentials.getPassword();

        if (LOG.isTraceEnabled()) {
            LOG.info("LDAP connection data and credentials: server={}, bindDN={}, password={}", ldapServer, bindDN, bindPassword);
        } else {
            LOG.info("LDAP connection data and credentials: server={}, bindDN={}, password=***", ldapServer, bindDN);

    public String getName() {
        return ldapServer;

    public Attributes getByDn(final String dn) throws NamingException {
        LdapContext ctx = new InitialLdapContext(env, null);
        Attributes result = ctx.getAttributes(dn);

        return result;

    public NamingEnumeration<SearchResult> search(final String baseDN, final String filter) throws NamingException {
        SearchControls searchControls = new SearchControls();

        LdapContext ctx = new InitialLdapContext(env, null);
        NamingEnumeration<SearchResult> result = ctx.search(baseDN, filter, searchControls);

        return result;