LdapManager.java 26.3 KB
Newer Older
Matt Tucker's avatar
Matt Tucker committed
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
Matt Tucker's avatar
Matt Tucker committed
6
 * Copyright (C) 2004 Jive Software. All rights reserved.
Matt Tucker's avatar
Matt Tucker committed
7
 *
Matt Tucker's avatar
Matt Tucker committed
8 9
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
Matt Tucker's avatar
Matt Tucker committed
10 11 12 13 14 15
 */

package org.jivesoftware.messenger.ldap;

import org.jivesoftware.messenger.JiveGlobals;
import org.jivesoftware.messenger.auth.UnauthorizedException;
Matt Tucker's avatar
Matt Tucker committed
16 17
import org.jivesoftware.util.Log;

Matt Tucker's avatar
Matt Tucker committed
18
import java.util.Hashtable;
Matt Tucker's avatar
Matt Tucker committed
19 20 21
import java.net.URLEncoder;
import javax.naming.*;
import javax.naming.directory.*;
Matt Tucker's avatar
Matt Tucker committed
22 23 24

/**
 * Centralized administration of LDAP connections. The getInstance() method
Matt Tucker's avatar
Matt Tucker committed
25
 * should be used to get an instace. The following configure this manager:<ul>
Matt Tucker's avatar
Matt Tucker committed
26 27 28 29 30 31 32 33 34 35
 *      <li> ldap.host
 *      <li> ldap.port
 *      <li> ldap.usernameField
 *      <li> ldap.baseDN
 *      <li> ldap.adminDN
 *      <li> ldap.adminPassword
 *      <li> ldap.ldapDebugEnabled
 *      <li> ldap.sslEnabled
 *      <li> ldap.initialContextFactory --  if this value is not specified,
 *          "com.sun.jndi.ldap.LdapCtxFactory" will be used instead.
Matt Tucker's avatar
Matt Tucker committed
36
 * </ul>
Matt Tucker's avatar
Matt Tucker committed
37 38 39 40 41 42 43 44 45 46 47
 *
 * @author Matt Tucker
 */
public class LdapManager {

    private String host;
    private int port = 389;
    private String usernameField = "uid";
    private String nameField = "cn";
    private String emailField = "mail";
    private String baseDN = "";
Matt Tucker's avatar
Matt Tucker committed
48
    private String alternateBaseDN = null;
Matt Tucker's avatar
Matt Tucker committed
49 50
    private String adminDN;
    private String adminPassword;
Matt Tucker's avatar
Matt Tucker committed
51
    private boolean ldapDebugEnabled = false;
Matt Tucker's avatar
Matt Tucker committed
52
    private boolean sslEnabled = false;
Matt Tucker's avatar
Matt Tucker committed
53 54
    private String initialContextFactory;
    private boolean connectionPoolEnabled = true;
Matt Tucker's avatar
Matt Tucker committed
55 56 57 58 59 60 61 62 63 64 65 66 67

    private static LdapManager instance = new LdapManager();

    /**
     * Provides singleton access to an instance of the LdapManager class.
     *
     * @return an LdapManager instance.
     */
    public static LdapManager getInstance() {
        return instance;
    }

    /**
Matt Tucker's avatar
Matt Tucker committed
68
     * Constructs a new LdapManager instance. This class is a singleton so the
Matt Tucker's avatar
Matt Tucker committed
69 70 71
     * constructor is private.
     */
    private LdapManager() {
72 73
        this.host = JiveGlobals.getXMLProperty("ldap.host");
        String portStr = JiveGlobals.getXMLProperty("ldap.port");
Matt Tucker's avatar
Matt Tucker committed
74 75 76 77
        if (portStr != null) {
            try {
                this.port = Integer.parseInt(portStr);
            }
Matt Tucker's avatar
Matt Tucker committed
78
            catch (NumberFormatException nfe) { }
Matt Tucker's avatar
Matt Tucker committed
79
        }
80 81
        if (JiveGlobals.getXMLProperty("ldap.usernameField") != null) {
            this.usernameField = JiveGlobals.getXMLProperty("ldap.usernameField");
Matt Tucker's avatar
Matt Tucker committed
82
        }
83 84
        if (JiveGlobals.getXMLProperty("ldap.baseDN") != null) {
            this.baseDN = JiveGlobals.getXMLProperty("ldap.baseDN");
Matt Tucker's avatar
Matt Tucker committed
85
        }
Matt Tucker's avatar
Matt Tucker committed
86 87 88
        if (JiveGlobals.getXMLProperty("ldap.alternateBaseDN") != null) {
            this.alternateBaseDN = JiveGlobals.getXMLProperty("ldap.alternateBaseDN");
        }
89 90
        if (JiveGlobals.getXMLProperty("ldap.nameField") != null) {
            this.nameField = JiveGlobals.getXMLProperty("ldap.nameField");
Matt Tucker's avatar
Matt Tucker committed
91
        }
92 93
        if (JiveGlobals.getXMLProperty("ldap.emailField") != null) {
            this.emailField = JiveGlobals.getXMLProperty("ldap.emailField");
Matt Tucker's avatar
Matt Tucker committed
94
        }
Matt Tucker's avatar
Matt Tucker committed
95 96 97 98
        if (JiveGlobals.getXMLProperty("ldap.connectionPoolEnabled") != null) {
            this.connectionPoolEnabled = Boolean.valueOf(
                    JiveGlobals.getXMLProperty("ldap.connectionPoolEnabled")).booleanValue();
        }
99 100
        this.adminDN = JiveGlobals.getXMLProperty("ldap.adminDN");
        this.adminPassword = JiveGlobals.getXMLProperty("ldap.adminPassword");
Matt Tucker's avatar
Matt Tucker committed
101
        this.ldapDebugEnabled = "true".equals(JiveGlobals.getXMLProperty("ldap.ldapDebugEnabled"));
102
        this.sslEnabled = "true".equals(JiveGlobals.getXMLProperty("ldap.sslEnabled"));
Matt Tucker's avatar
Matt Tucker committed
103 104 105 106 107 108 109 110 111
        this.initialContextFactory = JiveGlobals.getXMLProperty("ldap.initialContextFactory");
        if (initialContextFactory != null) {
            try {
                Class.forName(initialContextFactory);
            }
            catch (ClassNotFoundException cnfe) {
                Log.error("Initial context factory class failed to load: " + initialContextFactory +
                        ".  Using default initial context factory class instead.");
                initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
Matt Tucker's avatar
Matt Tucker committed
112 113
            }
        }
Matt Tucker's avatar
Matt Tucker committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
        // Use default value if none was set.
        else {
            initialContextFactory = "com.sun.jndi.ldap.LdapCtxFactory";
        }

        if (Log.isDebugEnabled()) {
            Log.debug("Created new LdapManager() instance, fields:");
            Log.debug("\t host: " + host);
            Log.debug("\t port: " + port);
            Log.debug("\t usernamefield: " + usernameField);
            Log.debug("\t baseDN: " + baseDN);
            Log.debug("\t alternateBaseDN: " + alternateBaseDN);
            Log.debug("\t nameField: " + nameField);
            Log.debug("\t emailField: " + emailField);
            Log.debug("\t adminDN: " + adminDN);
            Log.debug("\t adminPassword: " + adminPassword);
            Log.debug("\t ldapDebugEnabled: " + ldapDebugEnabled);
            Log.debug("\t sslEnabled: " + sslEnabled);
            Log.debug("\t initialContextFactory: " + initialContextFactory);
            Log.debug("\t connectionPoolEnabled: " + connectionPoolEnabled);
        }
Matt Tucker's avatar
Matt Tucker committed
135 136 137 138
    }

    /**
     * Returns a DirContext for the LDAP server that can be used to perform
Matt Tucker's avatar
Matt Tucker committed
139 140
     * lookups and searches using the default base DN. The context uses the
     * admin login that is defined by <tt>adminDN</tt> and <tt>adminPassword</tt>.
Matt Tucker's avatar
Matt Tucker committed
141 142 143 144 145
     *
     * @return a connection to the LDAP server.
     * @throws NamingException if there is an error making the LDAP connection.
     */
    public DirContext getContext() throws NamingException {
Matt Tucker's avatar
Matt Tucker committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
        return getContext(baseDN);
    }

    /**
     * Returns a DirContext for the LDAP server that can be used to perform
     * lookups and searches using the specified base DN. The context uses the
     * admin login that is defined by <tt>adminDN</tt> and <tt>adminPassword</tt>.
     *
     * @param baseDN the base DN to use for the context.
     * @return a connection to the LDAP server.
     * @throws NamingException if there is an error making the LDAP connection.
     */
    public DirContext getContext(String baseDN) throws NamingException {
        boolean debug = Log.isDebugEnabled();
        if (debug) {
            Log.debug("Creating a DirContext in LdapManager.getContext()...");
        }

         // Set up the environment for creating the initial context
Matt Tucker's avatar
Matt Tucker committed
165
        Hashtable env = new Hashtable();
Matt Tucker's avatar
Matt Tucker committed
166 167
        env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
        env.put(Context.PROVIDER_URL, getProviderURL(baseDN));
Matt Tucker's avatar
Matt Tucker committed
168
        if (sslEnabled) {
Matt Tucker's avatar
Matt Tucker committed
169 170
            env.put("java.naming.ldap.factory.socket",
                    "com.jivesoftware.util.ssl.DummySSLSocketFactory");
Matt Tucker's avatar
Matt Tucker committed
171 172 173 174 175 176 177 178 179 180 181
            env.put(Context.SECURITY_PROTOCOL, "ssl");
        }

        // Use simple authentication to connect as the admin.
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        if (adminDN != null) {
            env.put(Context.SECURITY_PRINCIPAL, adminDN);
        }
        if (adminPassword != null) {
            env.put(Context.SECURITY_CREDENTIALS, adminPassword);
        }
Matt Tucker's avatar
Matt Tucker committed
182
        if (ldapDebugEnabled) {
Matt Tucker's avatar
Matt Tucker committed
183 184
            env.put("com.sun.jndi.ldap.trace.ber", System.err);
        }
Matt Tucker's avatar
Matt Tucker committed
185 186 187
        if (connectionPoolEnabled) {
            env.put("com.sun.jndi.ldap.connect.pool", "true");
        }
Matt Tucker's avatar
Matt Tucker committed
188

Matt Tucker's avatar
Matt Tucker committed
189 190 191
        if (debug) {
            Log.debug("Created hashtable with context values, attempting to create context...");
        }
Matt Tucker's avatar
Matt Tucker committed
192
        // Create new initial context
Matt Tucker's avatar
Matt Tucker committed
193 194 195 196 197
        DirContext context = new InitialDirContext(env);
        if (debug) {
            Log.debug("... context created successfully, returning.");
        }
        return context;
Matt Tucker's avatar
Matt Tucker committed
198 199 200 201 202 203
    }

    /**
     * Returns true if the user is able to successfully authenticate against
     * the LDAP server. The "simple" authentication protocol is used.
     *
Matt Tucker's avatar
Matt Tucker committed
204
     * @param userDN the user's dn to authenticate (relative to <tt>baseDN</tt>).
Matt Tucker's avatar
Matt Tucker committed
205 206 207 208
     * @param password the user's password.
     * @return true if the user successfully authenticates.
     */
    public boolean checkAuthentication(String userDN, String password) {
Matt Tucker's avatar
Matt Tucker committed
209 210 211 212 213
        boolean debug = Log.isDebugEnabled();
        if (debug) {
            Log.debug("In LdapManager.checkAuthentication(userDN, password), userDN is: " + userDN + "...");
        }

Matt Tucker's avatar
Matt Tucker committed
214 215 216 217
        DirContext ctx = null;
        try {
            // See if the user authenticates.
            Hashtable env = new Hashtable();
Matt Tucker's avatar
Matt Tucker committed
218 219
            env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
            env.put(Context.PROVIDER_URL, getProviderURL(baseDN));
Matt Tucker's avatar
Matt Tucker committed
220
            if (sslEnabled) {
Matt Tucker's avatar
Matt Tucker committed
221
                env.put("java.naming.ldap.factory.socket", "com.jivesoftware.util.ssl.DummySSLSocketFactory");
Matt Tucker's avatar
Matt Tucker committed
222 223 224 225 226
                env.put(Context.SECURITY_PROTOCOL, "ssl");
            }
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, userDN + "," + baseDN);
            env.put(Context.SECURITY_CREDENTIALS, password);
Matt Tucker's avatar
Matt Tucker committed
227
            if (ldapDebugEnabled) {
Matt Tucker's avatar
Matt Tucker committed
228 229
                env.put("com.sun.jndi.ldap.trace.ber", System.err);
            }
Matt Tucker's avatar
Matt Tucker committed
230 231 232
            if (debug) {
                Log.debug("Created context values, attempting to create context...");
            }
Matt Tucker's avatar
Matt Tucker committed
233
            ctx = new InitialDirContext(env);
Matt Tucker's avatar
Matt Tucker committed
234 235 236
            if (debug) {
                Log.debug("... context created successfully, returning.");
            }
Matt Tucker's avatar
Matt Tucker committed
237 238
        }
        catch (NamingException ne) {
Matt Tucker's avatar
Matt Tucker committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
            // If an alt baseDN is defined, attempt a lookup there.
            if (alternateBaseDN != null) {
                try { ctx.close(); }
                catch (Exception ignored) { }
                try {
                    // See if the user authenticates.
                    Hashtable env = new Hashtable();
                    // Use a custom initial context factory if specified. Otherwise, use the default.
                    env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
                    env.put(Context.PROVIDER_URL, getProviderURL(alternateBaseDN));
                    if (sslEnabled) {
                        env.put("java.naming.ldap.factory.socket", "com.jivesoftware.util.ssl.DummySSLSocketFactory");
                        env.put(Context.SECURITY_PROTOCOL, "ssl");
                    }
                    env.put(Context.SECURITY_AUTHENTICATION, "simple");
                    env.put(Context.SECURITY_PRINCIPAL, userDN + "," + alternateBaseDN);
                    env.put(Context.SECURITY_CREDENTIALS, password);
                    if (ldapDebugEnabled) {
                        env.put("com.sun.jndi.ldap.trace.ber", System.err);
                    }
                    if (debug) {
                        Log.debug("Created context values, attempting to create context...");
                    }
                    ctx = new InitialDirContext(env);
                }
                catch (NamingException e) {
                    if (debug) {
                        Log.debug("Caught a naming exception when creating InitialContext", ne);
                    }
                    return false;
                }
Matt Tucker's avatar
Matt Tucker committed
270
            }
Matt Tucker's avatar
Matt Tucker committed
271 272 273 274 275
            else {
                if (debug) {
                    Log.debug("Caught a naming exception when creating InitialContext", ne);
                }
                return false;
Matt Tucker's avatar
Matt Tucker committed
276 277
            }
        }
Matt Tucker's avatar
Matt Tucker committed
278 279 280 281
        finally {
            try { ctx.close(); }
            catch (Exception ignored) { }
        }
Matt Tucker's avatar
Matt Tucker committed
282 283 284 285 286 287 288
        return true;
    }

    /**
     * Finds a user's dn using their username. Normally, this search will
     * be performed using the field "uid", but this can be changed by setting
     * the <tt>usernameField</tt> property.<p>
Matt Tucker's avatar
Matt Tucker committed
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
     *
     * Searches are performed over all subtrees relative to the <tt>baseDN</tt>.
     * If the search fails in the <tt>baseDN</tt> then another search will be
     * performed in the <tt>alternateBaseDN</tt>. For example, if the <tt>baseDN</tt>
     * is "o=jivesoftware, o=com" and we do a search for "mtucker", then we might
     * find a userDN of "uid=mtucker,ou=People". This kind of searching is a good
     * thing since it doesn't make the assumption that all user records are stored
     * in a flat structure. However, it does add the requirement that "uid" field
     * (or the other field specified) must be unique over the entire subtree from
     * the <tt>baseDN</tt>. For example, it's entirely possible to create two dn's
     * in your LDAP directory with the same uid: "uid=mtucker,ou=People" and
     * "uid=mtucker,ou=Administrators". In such a case, it's not possible to
     * uniquely identify a user, so this method will throw an error.<p>
     *
     * The dn that's returned is relative to the default <tt>baseDN</tt>.
     *
     * @param username the username to lookup the dn for.
     * @return the dn associated with <tt>username</tt>.
     * @throws Exception if the search for the dn fails.
     */
    public String findUserDN(String username) throws Exception {
        try {
            return findUserDN(username, baseDN);
        }
        catch (Exception e) {
            if (alternateBaseDN != null) {
                return findUserDN(username, alternateBaseDN);
            }
            else {
                throw e;
            }
        }
    }

    /**
     * Finds a user's dn using their username in the specified baseDN. Normally, this search
     * will be performed using the field "uid", but this can be changed by setting
     * the <tt>usernameField</tt> property.<p>
     *
Matt Tucker's avatar
Matt Tucker committed
328 329 330 331 332 333 334 335 336 337 338
     * Searches are performed over all subtrees relative to the <tt>baseDN</tt>.
     * For example, if the <tt>baseDN</tt> is "o=jivesoftware, o=com" and we
     * do a search for "mtucker", then we might find a userDN of
     * "uid=mtucker,ou=People". This kind of searching is a good thing since
     * it doesn't make the assumption that all user records are stored in a flat
     * structure. However, it does add the requirement that "uid" field (or the
     * other field specified) must be unique over the entire subtree from the
     * <tt>baseDN</tt>. For example, it's entirely possible to create two dn's
     * in your LDAP directory with the same uid: "uid=mtucker,ou=People" and
     * "uid=mtucker,ou=Administrators". In such a case, it's not possible to
     * uniquely identify a user, so this method will throw an error.<p>
Matt Tucker's avatar
Matt Tucker committed
339
     *
Matt Tucker's avatar
Matt Tucker committed
340 341 342
     * The dn that's returned is relative to the <tt>baseDN</tt>.
     *
     * @param username the username to lookup the dn for.
Matt Tucker's avatar
Matt Tucker committed
343
     * @param baseDN the base DN to use for this search.
Matt Tucker's avatar
Matt Tucker committed
344 345
     * @return the dn associated with <tt>username</tt>.
     * @throws Exception if the search for the dn fails.
Matt Tucker's avatar
Matt Tucker committed
346
     * @see #findUserDN(String)  to search using the default baseDN and alternateBaseDN.
Matt Tucker's avatar
Matt Tucker committed
347
     */
Matt Tucker's avatar
Matt Tucker committed
348 349 350 351 352 353
    public String findUserDN(String username, String baseDN) throws Exception {
        boolean debug = Log.isDebugEnabled();
        if (debug) {
            Log.debug("Trying to find a user's DN based on their username. " + usernameField + ": " + username
                    + ", Base DN: " + baseDN + "...");
        }
Matt Tucker's avatar
Matt Tucker committed
354 355
        DirContext ctx = null;
        try {
Matt Tucker's avatar
Matt Tucker committed
356 357 358 359
            ctx = getContext(baseDN);
            if (debug) {
                Log.debug("Starting LDAP search...");
            }
Matt Tucker's avatar
Matt Tucker committed
360 361 362
            // Search for the dn based on the username.
            SearchControls constraints = new SearchControls();
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
Matt Tucker's avatar
Matt Tucker committed
363
            constraints.setReturningAttributes(new String[] { usernameField });
Matt Tucker's avatar
Matt Tucker committed
364 365 366 367 368 369

            StringBuffer filter = new StringBuffer();
            filter.append("(").append(usernameField).append("=");
            filter.append(username).append(")");

            NamingEnumeration answer = ctx.search("", filter.toString(), constraints);
Matt Tucker's avatar
Matt Tucker committed
370 371 372 373 374

            if (debug) {
                Log.debug("... search finished");
            }

Matt Tucker's avatar
Matt Tucker committed
375
            if (answer == null || !answer.hasMoreElements()) {
Matt Tucker's avatar
Matt Tucker committed
376 377 378
                if (debug) {
                    Log.debug("User DN based on username '" + username + "' not found.");
                }
Matt Tucker's avatar
Matt Tucker committed
379 380 381 382
                throw new UnauthorizedException("Username " + username + " not found");
            }
            String userDN = ((SearchResult)answer.next()).getName();
            // Make sure there are no more search results. If there are, then
383
            // the username isn't unique on the LDAP server (a perfectly possible
Matt Tucker's avatar
Matt Tucker committed
384 385 386 387
            // scenario since only fully qualified dn's need to be unqiue).
            // There really isn't a way to handle this, so throw an exception.
            // The baseDN must be set correctly so that this doesn't happen.
            if (answer.hasMoreElements()) {
Matt Tucker's avatar
Matt Tucker committed
388 389 390 391 392
                if (debug) {
                    Log.debug("Search for userDN based on username '" + username + "' found multiple " +
                            "responses, throwing exception.");
                }
                throw new Exception ("LDAP username lookup for " + username +
Matt Tucker's avatar
Matt Tucker committed
393 394 395 396
                        " matched multiple entries.");
            }
            return userDN;
        }
Matt Tucker's avatar
Matt Tucker committed
397 398 399
        catch (Exception e) {
            if (debug) {
                Log.debug("Exception thrown when searching for userDN based on username '" + username + "'", e);
Matt Tucker's avatar
Matt Tucker committed
400
            }
Matt Tucker's avatar
Matt Tucker committed
401 402 403 404 405
            throw e;
        }
        finally {
            try { ctx.close(); }
            catch (Exception ignored) { }
Matt Tucker's avatar
Matt Tucker committed
406 407 408
        }
    }

Matt Tucker's avatar
Matt Tucker committed
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
    /**
     * Returns a properly encoded URL for use as the PROVIDER_URL.
     * If the encoding fails then the URL will contain the raw base dn.
     *
     * @param baseDN the base dn to use in the URL.
     * @return the properly encoded URL for use in as PROVIDER_URL.
     */
    private String getProviderURL(String baseDN) {
        String ldapURL = "";
        try {
            // Create a correctly-encoded ldap URL for the PROVIDER_URL
            ldapURL = "ldap://" + host + ":" + port + "/" +
                    URLEncoder.encode(baseDN, "UTF-8");
            // The java.net.URLEncoder class encodes spaces as +, but they need to be %20
            ldapURL = ldapURL.replaceAll("\\+", "%20");
        }
        catch (java.io.UnsupportedEncodingException e) {
            // UTF-8 is not supported, fall back to using raw baseDN
            ldapURL = "ldap://" + host + ":" + port + "/" + baseDN;
        }
        return ldapURL;
    }

Matt Tucker's avatar
Matt Tucker committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
    /**
     * Returns the LDAP server host; e.g. <tt>localhost</tt> or
     * <tt>machine.example.com</tt>, etc. This value is stored as the Jive
     * Property <tt>ldap.host</tt>.
     *
     * @return the LDAP server host name.
     */
    public String getHost() {
        return host;
    }

    /**
     * Sets the LDAP server host; e.g., <tt>localhost</tt> or
     * <tt>machine.example.com</tt>, etc. This value is store as the Jive
     * Property <tt>ldap.host</tt>
     *
     * @param host the LDAP server host name.
     */
    public void setHost(String host) {
        this.host = host;
452
        JiveGlobals.setXMLProperty("ldap.host", host);
Matt Tucker's avatar
Matt Tucker committed
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
    }

    /**
     * Returns the LDAP server port number. The default is 389. This value is
     * stored as the Jive Property <tt>ldap.port</tt>.
     *
     * @return the LDAP server port number.
     */
    public int getPort() {
        return port;
    }

    /**
     * Sets the LDAP server port number. The default is 389. This value is
     * stored as the Jive property <tt>ldap.port</tt>.
     *
     * @param port the LDAP server port number.
     */
    public void setPort(int port) {
        this.port = port;
Matt Tucker's avatar
Matt Tucker committed
473
        JiveGlobals.setXMLProperty("ldap.port", ""+port);
Matt Tucker's avatar
Matt Tucker committed
474 475 476 477 478 479 480 481 482 483
    }

    /**
     * Returns true if LDAP connection debugging is turned on. When on, trace
     * information about BER buffers sent and received by the LDAP provider is
     * written to System.out. Debugging is turned off by default.
     *
     * @return true if LDAP debugging is turned on.
     */
    public boolean isDebugEnabled() {
Matt Tucker's avatar
Matt Tucker committed
484
        return ldapDebugEnabled;
Matt Tucker's avatar
Matt Tucker committed
485 486 487 488 489 490 491 492 493 494
    }

    /**
     * Sets whether LDAP connection debugging is turned on. When on, trace
     * information about BER buffers sent and received by the LDAP provider is
     * written to System.out. Debugging is turned off by default.
     *
     * @param debugEnabled true if debugging should be turned on.
     */
    public void setDebugEnabled(boolean debugEnabled) {
Matt Tucker's avatar
Matt Tucker committed
495 496
        this.ldapDebugEnabled = debugEnabled;
        JiveGlobals.setXMLProperty("ldap.ldapDebugEnabled", ""+debugEnabled);
Matt Tucker's avatar
Matt Tucker committed
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    }

    /**
     * Returns true if LDAP connection is via SSL or not. SSL is turned off by default.
     *
     * @return true if SSL connections are enabled or not.
     */
    public boolean isSslEnabled() {
        return sslEnabled;
    }

    /**
     * Sets whether the connection to the LDAP server should be made via ssl or not.
     *
     * @param sslEnabled true if ssl should be enabled, false otherwise.
     */
    public void setSslEnabled(boolean sslEnabled) {
        this.sslEnabled = sslEnabled;
Matt Tucker's avatar
Matt Tucker committed
515
        JiveGlobals.setXMLProperty("ldap.sslEnabled", ""+sslEnabled);
Matt Tucker's avatar
Matt Tucker committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    }

    /**
     * Returns the LDAP field name that the username lookup will be performed
     * on. By default this is "uid".
     *
     * @return the LDAP field that the username lookup will be performed on.
     */
    public String getUsernameField() {
        return usernameField;
    }

    /**
     * Sets the LDAP field name that the username lookup will be performed on.
     * By default this is "uid".
     *
     * @param usernameField the LDAP field that the username lookup will be
Matt Tucker's avatar
Matt Tucker committed
533
     *      performed on.
Matt Tucker's avatar
Matt Tucker committed
534 535 536 537
     */
    public void setUsernameField(String usernameField) {
        this.usernameField = usernameField;
        if (usernameField == null) {
538
            JiveGlobals.deleteXMLProperty("ldap.usernameField");
Matt Tucker's avatar
Matt Tucker committed
539 540
        }
        else {
541
            JiveGlobals.setXMLProperty("ldap.usernameField", usernameField);
Matt Tucker's avatar
Matt Tucker committed
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
        }
    }

    /**
     * Returns the LDAP field name that the user's name is stored in. By default
     * this is "cn". Another common value is "displayName".
     *
     * @return the LDAP field that that correspond's to the user's name.
     */
    public String getNameField() {
        return nameField;
    }

    /**
     * Sets the LDAP field name that the user's name is stored in. By default
     * this is "cn". Another common value is "displayName".
     *
     * @param nameField the LDAP field that that correspond's to the user's name.
     */
    public void setNameField(String nameField) {
        this.nameField = nameField;
        if (nameField == null) {
564
            JiveGlobals.deleteXMLProperty("ldap.nameField");
Matt Tucker's avatar
Matt Tucker committed
565 566
        }
        else {
567
            JiveGlobals.setXMLProperty("ldap.nameField", nameField);
Matt Tucker's avatar
Matt Tucker committed
568 569 570 571 572 573 574 575
        }
    }

    /**
     * Returns the LDAP field name that the user's email address is stored in.
     * By default this is "mail".
     *
     * @return the LDAP field that that correspond's to the user's email
Matt Tucker's avatar
Matt Tucker committed
576
     *      address.
Matt Tucker's avatar
Matt Tucker committed
577 578 579 580 581 582 583 584 585 586
     */
    public String getEmailField() {
        return emailField;
    }

    /**
     * Sets the LDAP field name that the user's email address is stored in.
     * By default this is "mail".
     *
     * @param emailField the LDAP field that that correspond's to the user's
Matt Tucker's avatar
Matt Tucker committed
587
     *      email address.
Matt Tucker's avatar
Matt Tucker committed
588 589 590 591
     */
    public void setEmailField(String emailField) {
        this.emailField = emailField;
        if (emailField == null) {
592
            JiveGlobals.deleteXMLProperty("ldap.emailField");
Matt Tucker's avatar
Matt Tucker committed
593 594
        }
        else {
595
            JiveGlobals.setXMLProperty("ldap.emailField", emailField);
Matt Tucker's avatar
Matt Tucker committed
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
        }
    }

    /**
     * Returns the starting DN that searches for users will performed with.
     * Searches will performed on the entire sub-tree under the base DN.
     *
     * @return the starting DN used for performing searches.
     */
    public String getBaseDN() {
        return baseDN;
    }

    /**
     * Sets the starting DN that searches for users will performed with.
     * Searches will performed on the entire sub-tree under the base DN.
     *
     * @param baseDN the starting DN used for performing searches.
     */
    public void setBaseDN(String baseDN) {
        this.baseDN = baseDN;
617
        JiveGlobals.setXMLProperty("ldap.baseDN", baseDN);
Matt Tucker's avatar
Matt Tucker committed
618 619
    }

Matt Tucker's avatar
Matt Tucker committed
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
    /**
     * Returns the alternate starting DN that searches for users will performed with.
     * Searches will performed on the entire sub-tree under the alternate base DN after
     * they are performed on the main base DN.
     *
     * @return the alternate starting DN used for performing searches. If no alternate
     *      DN is set, this method will return <tt>null</tt>.
     */
    public String getAlternateBaseDN() {
        return alternateBaseDN;
    }

    /**
     * Sets the alternate starting DN that searches for users will performed with.
     * Searches will performed on the entire sub-tree under the alternate base DN after
     * they are performed on the main base dn.
     *
     * @param alternateBaseDN the alternate starting DN used for performing searches.
     */
    public void setAlternateBaseDN(String alternateBaseDN) {
        this.alternateBaseDN = alternateBaseDN;
        if (alternateBaseDN == null) {
            JiveGlobals.deleteXMLProperty("ldap.alternateBaseDN");
        }
        else {
            JiveGlobals.setXMLProperty("ldap.alternateBaseDN", alternateBaseDN);
        }
    }

Matt Tucker's avatar
Matt Tucker committed
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
    /**
     * Returns the starting admin DN that searches for admins will performed with.
     * Searches will performed on the entire sub-tree under the admin DN.
     *
     * @return the starting DN used for performing searches.
     */
    public String getAdminDN() {
        return adminDN;
    }

    /**
     * Sets the starting admin DN that searches for admins will performed with.
     * Searches will performed on the entire sub-tree under the admins DN.
     *
     * @param adminDN the starting DN used for performing admin searches.
     */
    public void setAdminDN(String adminDN) {
        this.adminDN = adminDN;
667
        JiveGlobals.setXMLProperty("ldap.adminDN", adminDN);
Matt Tucker's avatar
Matt Tucker committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
    }

    /**
     * Returns the starting admin DN that searches for admins will performed with.
     * Searches will performed on the entire sub-tree under the admin DN.
     *
     * @return the starting DN used for performing searches.
     */
    public String getAdminPassword() {
        return adminPassword;
    }

    /**
     * Sets the admin password for the LDAP server we're connecting to.
     *
     * @param adminPassword the admin password for the LDAP server we're
Matt Tucker's avatar
Matt Tucker committed
684
     * connecting to.
Matt Tucker's avatar
Matt Tucker committed
685 686 687
     */
    public void setAdminPassword(String adminPassword) {
        this.adminPassword = adminPassword;
688
        JiveGlobals.setXMLProperty("ldap.adminPassword", adminPassword);
Matt Tucker's avatar
Matt Tucker committed
689 690
    }
}