LdapAuthorizationMapping.java 5.62 KB
Newer Older
1 2 3 4 5
/**
 * $RCSfile$
 * $Revision: $
 * $Date: 2006-04-07 09:28:54 -0500 (Fri, 07 Apr 2006) $
 *
6
 * Copyright (C) 2004-2008 Jive Software. All rights reserved.
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * 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.
19 20 21 22
 */

package org.jivesoftware.openfire.ldap;

23
import javax.naming.NamingEnumeration;
24 25 26 27 28 29
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

30 31 32 33 34
import org.jivesoftware.openfire.auth.AuthorizationMapping;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

35 36 37 38 39


/**
 * Provider for authorization mapping using LDAP. If the authenticated
 * principal did not request a username, provide one via LDAP. Specify the
40
 * lookup field in the system properties. An entry in that file would
41
 * look like the following:
42 43 44 45 46
 *
 * <ul>
 * <li><tt>ldap.princField = k5login</tt></li>
 * <li><tt>ldap.princSearchFilter = princField={0}</tt></li>
 * </ul>
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
 * <p/>
 * Each ldap object that represents a user is expcted to have exactly one of
 * ldap.usernameField and ldap.princField, and they are both expected to be unique
 * over the search base.  A search will be performed over all objects where 
 * princField = principal, and the usernameField will be returned.
 * Note that it is expected this search return exactly one object. (There can
 * only be one default) If more than one is returned, the first entry 
 * encountered will be used, and no sorting is performed or requested.
 * If more control over the search is needed, you can specify the mapSearchFilter
 * used to perform the LDAP query. 
 * This implementation requires that LDAP be configured, obviously.
 *
 *
 * @author Jay Kline
 */
public class LdapAuthorizationMapping implements AuthorizationMapping {

64 65
	private static final Logger Log = LoggerFactory.getLogger(LdapAuthorizationMapping.class);

66 67 68 69 70 71
    private LdapManager manager;
    private String usernameField;
    private String princField;
    private String princSearchFilter;

    public LdapAuthorizationMapping() {
72 73 74 75
        // Convert XML based provider setup to Database based
        JiveGlobals.migrateProperty("ldap.princField");
        JiveGlobals.migrateProperty("ldap.princSearchFilter");

76 77
        manager = LdapManager.getInstance();
        usernameField = manager.getUsernameField();
78 79
        princField = JiveGlobals.getProperty("ldap.princField", "k5login");
        princSearchFilter = JiveGlobals.getProperty("ldap.princSearchFilter");
80 81 82 83 84 85 86 87 88 89 90 91 92 93
        StringBuilder filter = new StringBuilder();
        if(princSearchFilter == null) {
            filter.append("(").append(princField).append("={0})");
        } else {
            filter.append("(&(").append(princField).append("={0})(");
            filter.append(princSearchFilter).append("))");
        }
        princSearchFilter = filter.toString();
    }

    public String map(String principal) {
        String username = principal;
        DirContext ctx = null;
        try {
94
            Log.debug("LdapAuthorizationMapping: Starting LDAP search...");
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
            String usernameField = manager.getUsernameField();
            String baseDN = manager.getBaseDN();
            boolean subTreeSearch = manager.isSubTreeSearch();
            ctx = manager.getContext();
            SearchControls constraints = new SearchControls();
            if (subTreeSearch) {
                constraints.setSearchScope
            (SearchControls.SUBTREE_SCOPE);
            }
            // Otherwise, only search a single level.
            else {
                constraints.setSearchScope(SearchControls.ONELEVEL_SCOPE);
            }
            constraints.setReturningAttributes(new String[] { usernameField });

            NamingEnumeration answer = ctx.search("", princSearchFilter, new String[] {principal},
                    constraints);
112
            Log.debug("LdapAuthorizationMapping: ... search finished");
113
            if (answer == null || !answer.hasMoreElements()) {
114
                Log.debug("LdapAuthorizationMapping: Username based on principal '" + principal + "' not found.");
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
                return principal;
            }
            Attributes atrs = ((SearchResult)answer.next()).getAttributes();
            Attribute usernameAttribute = atrs.get(usernameField);
            username = (String) usernameAttribute.get();
        }
        catch (Exception e) {
            // Ignore.
        }
        finally {
            try {
                if (ctx != null) {
                    ctx.close();
                }
            }
            catch (Exception ignored) {
                // Ignore.
            }
        }
        return username;
    }

    /**
     * Returns the short name of the Policy
     *
     * @return The short name of the Policy
     */
    public String name() {
        return "LDAP Authorization Mapping";
    }

    /**
     * Returns a description of the Policy
     *
     * @return The description of the Policy.
     */
    public String description() {
        return "Provider for authorization using LDAP. Returns the principals default username using the attribute specified in ldap.princField.";
    }
}