• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/extensions/security/ldap/src/main/java/org/exist/security/realm/ldap/LdapContextFactory.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.security.realm.ldap;
50

51
import java.text.MessageFormat;
52
import java.util.Hashtable;
53
import java.util.Map;
54
import javax.naming.Context;
55
import javax.naming.NamingException;
56
import javax.naming.ldap.InitialLdapContext;
57
import javax.naming.ldap.LdapContext;
58

59
import org.apache.logging.log4j.LogManager;
60
import org.apache.logging.log4j.Logger;
61
import org.exist.config.Configurable;
62
import org.exist.config.Configuration;
63
import org.exist.config.Configurator;
64
import org.exist.config.annotation.ConfigurationClass;
65
import org.exist.config.annotation.ConfigurationFieldAsElement;
66

67
import static org.exist.util.StringUtil.isNullOrEmptyOrWs;
68

69
/**
70
 * @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
71
 */
72
@ConfigurationClass("context")
73
public class LdapContextFactory implements Configurable {
74

75
    private static final Logger LOG = LogManager.getLogger(LdapContextFactory.class);
×
76

77
    private static final String SUN_CONNECTION_POOLING_PROPERTY = "com.sun.jndi.ldap.connect.pool";
78

79
    @ConfigurationFieldAsElement("authentication")
×
80
    protected String authentication = "simple";
81

82
    @ConfigurationFieldAsElement("use-ssl")
×
83
    private final boolean ssl = false;
84

85
    @ConfigurationFieldAsElement("principal-pattern")
×
86
    protected String principalPattern = null;
87
    protected MessageFormat principalPatternFormat;
88

89
    @ConfigurationFieldAsElement("url")
×
90
    protected String url = null;
91

92
    @ConfigurationFieldAsElement("domain")
×
93
    protected String domain = null;
94

95
    protected String contextFactoryClassName = "com.sun.jndi.ldap.LdapCtxFactory";
×
96

97
    protected String systemUsername = null;
×
98

99
    protected String systemPassword = null;
×
100

101
    private boolean usePooling = true;
×
102

103
    private Configuration configuration = null;
×
104

105
    @ConfigurationFieldAsElement("search")
106
    private LDAPSearchContext search;
107

108
    @ConfigurationFieldAsElement("transformation")
109
    private LDAPTransformationContext realmTransformation;
110

111
    public LdapContextFactory(final Configuration config) {
×
112
        configuration = Configurator.configure(this, config);
×
113
        if (principalPattern != null) {
×
114
            principalPatternFormat = new MessageFormat(principalPattern);
×
115
        }
116
    }
×
117

118
    public LdapContext getSystemLdapContext() throws NamingException {
119
        return getLdapContext(systemUsername, systemPassword);
×
120
    }
121

122
    public LdapContext getLdapContext(final String username, final String password) throws NamingException {
123
        return getLdapContext(username, password, null);
×
124
    }
125

126
    public LdapContext getLdapContext(String username, final String password, final Map<String, Object> additionalEnv) throws NamingException {
127

128
        if (url == null) {
×
129
            throw new IllegalStateException("An LDAP URL must be specified of the form ldap://<hostname>:<port>");
×
130
        }
131

132
        if (isNullOrEmptyOrWs(password)) {
×
133
            throw new IllegalStateException("Password for LDAP authentication may not be empty.");
×
134
        }
135

136
        if (username != null && principalPattern != null) {
×
137
            username = principalPatternFormat.format(new String[]{username});
×
138
        }
139

140
        final Hashtable<String, Object> env = new Hashtable<>();
×
141

142
        env.put(Context.SECURITY_AUTHENTICATION, authentication);
×
143
        if (ssl) {
144
            env.put(Context.SECURITY_PROTOCOL, "ssl");
145
        }
146

147
        if (username != null) {
×
148
            env.put(Context.SECURITY_PRINCIPAL, username);
×
149
        }
150

151
        if (password != null) {
×
152
            env.put(Context.SECURITY_CREDENTIALS, password);
×
153
        }
154

155
        env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClassName);
×
156
        env.put(Context.PROVIDER_URL, url);
×
157

158
        //Absolutely nessecary for working with Active Directory
159
        env.put("java.naming.ldap.attributes.binary", "objectSid");
×
160

161
        // the following is helpful in debugging errors
162
        //env.put("com.sun.jndi.ldap.trace.ber", System.err);
163

164
        // Only pool connections for system contexts
165
        if (usePooling && username != null && username.equals(systemUsername)) {
×
166
            // Enable connection pooling
167
            env.put(SUN_CONNECTION_POOLING_PROPERTY, "true");
×
168
        }
169

170
        if (additionalEnv != null) {
×
171
            env.putAll(additionalEnv);
×
172
        }
173

174
        if (LOG.isDebugEnabled()) {
×
175
            LOG.debug("Initializing LDAP context using URL [{}] and username [{}] with pooling [{}]", url, username, usePooling ? "enabled" : "disabled");
×
176
        }
177

178
        return new InitialLdapContext(env, null);
×
179
    }
180

181
    public LDAPSearchContext getSearch() {
182
        return search;
×
183
    }
184

185
    public LDAPTransformationContext getTransformationContext() {
186
        return realmTransformation;
×
187
    }
188

189
    public String getDomain() {
190
        return domain;
×
191
    }
192

193
    // configurable methods
194
    @Override
195
    public boolean isConfigured() {
196
        return (configuration != null);
×
197
    }
198

199
    @Override
200
    public Configuration getConfiguration() {
201
        return configuration;
×
202
    }
203
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc