Package anvil.server.ldap

Source Code of anvil.server.ldap.LDAPRealm

/*
* $Id: LDAPRealm.java,v 1.12 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.server.ldap;

import anvil.Log;
import anvil.java.util.BindingEnumeration;
import anvil.java.security.PermissionCollectionCombiner;
import anvil.core.Any;
import anvil.core.Serialization;
import anvil.java.util.Hashlist;
import anvil.core.Array;
import anvil.database.ConnectionManager;
import anvil.database.PooledConnection;

import anvil.server.PolicyPreferences;
import anvil.server.RealmPreferences;
import anvil.server.Citizen;
import anvil.server.Realm;
import anvil.server.Tribe;
import anvil.server.Zone;
import anvil.server.Realm;
import anvil.server.Tribe;
import anvil.server.Citizen;
import anvil.server.OperationFailedException;
import anvil.server.CitizenNotFoundException;

import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Enumeration;
import java.util.ArrayList;
import java.security.Permission;
import java.security.Permissions;
import java.security.PermissionCollection;

import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.MalformedPatternException;

import javax.naming.*;
import javax.naming.directory.*;

/**
* class LDAPRealm
* Implements Anvil Realm architecture over LDAP.
*
* TODO:
* - tribe.attach(tribe) loop check
* - construct ctz.displayName from first+surname/username
*
* @author: Simo Tuokko
*/

public class LDAPRealm implements Realm
{

  private Map       _users = new HashMap();
  private Map       _groups = new HashMap();
  private Zone      _zone;
  private String    _name;
  private String    _prefix = null;
  private String    _contextPool = "authen";
  private LDAPTribe _rootTribe = null;

  private ConnectionManager _manager = null;

  private static String ROOT_TRIBE = "Root Tribe";
  private static Pattern EMAIL_PATTERN;
  private static Attribute objectClassAttr;
  private static Attribute groupObjectClass;
  static {
    try {
      EMAIL_PATTERN = new Perl5Compiler().compile("^([a-z0-9_\\.\\-])+\\@(([a-z0-9\\-])+\\.)+([a-z0-9]){2,4}$");
    } catch(MalformedPatternException e) {}
   
    objectClassAttr = new BasicAttribute("objectclass");
    objectClassAttr.add("top");
    objectClassAttr.add("person");
    objectClassAttr.add("organizationalPerson");
    objectClassAttr.add("inetorgperson");

    groupObjectClass = new BasicAttribute("objectclass");
    groupObjectClass.add("top");
    groupObjectClass.add("groupofuniquenames");
  }

 
  public LDAPRealm()
  {
  }


  public String toString()
  {
    return "LDAPRealm("+_name+"@"+_contextPool+"@"+_prefix+")";
  }
 

  public void initialize(RealmPreferences prefs)
  {
    _name = prefs.getName();
    _zone = prefs.getParent();
   
    //get connection manager for contextPool
    _contextPool = (String)prefs.getPreference("contextPool");
    _prefix = (String)prefs.getPreference("prefix");
   
    if (_prefix == null) {
      _zone.log().error("LDAPRealm: 'prefix' not found from configuration!");
    }
    if (_contextPool == null) {
      _zone.log().error("LDAPRealm: contextPool name not found from configuration, using default: authen");
    }
    try {
      _manager = _zone.getManagerFor(_contextPool);
    } catch(Exception e) {
      _zone.log().error("LDAPRealm: error while getting ConnectionManager: "+e);
    }

    _zone.log().info("Realm " + this + " initialized");
  }


  public void stop()
  {
    _zone.log().info("Realm " + this + " stopped");
  }
 
 
  public Citizen getCitizen(String username)
  {
    Citizen c = null;
   
    if (!_users.containsKey(username)) {
      try {
        c = new LDAPCitizen(this, username);
        _users.put(username, c);
      } catch(CitizenNotFoundException cnfe) {
        //return null
       
      } catch(OperationFailedException e) {
        _zone.log().error("LDAPRealm.getCitizen() failed: "+e);
      }
    } else {
      c = (Citizen)_users.get(username);
    }
   
    return c;
  }

 
  public Tribe getTribe(String name)
  {
    Tribe t = null;
   
    if (!_groups.containsKey(name)) {
      try {
        t = new LDAPTribe(this, name);
        _groups.put(name, t);
      } catch(CitizenNotFoundException cnfe) {
        _zone.log().error("LDAPRealm.getTribe() Tribe '"+name+"' not found!");
       
      } catch(OperationFailedException e) {
        _zone.log().error("LDAPRealm.getTribe() failed: "+e);
      }
    } else {
      t = (Tribe)_groups.get(name);
    }
   
    return t;
  }

 
  public Citizen[] searchCitizenByVariable(String variable, String value)
  {
    if (variable == null || !LDAPCitizen.ATTRMAP_C.containsKey(variable)) {
      _zone.log().error("LDAPRealm doesn't support search for: "+variable);
      return null;
    }
   
    PooledConnection connImpl = null;
    DirContext ctx = null;
    ArrayList result = new ArrayList();
 
    try {
      connImpl = getConnection();
      ctx = (DirContext)connImpl.getConnection();
 
      String search = "("+LDAPCitizen.ATTRMAP_C.get(variable)+"="+value+")";
      SearchControls sc = new SearchControls();
      sc.setReturningAttributes(new String[] { "uid" });
      NamingEnumeration enu = ctx.search("ou=users", search, sc);
 
      while (enu.hasMore()) {
        SearchResult s = (SearchResult)enu.next();
        Attributes attrs = s.getAttributes();
        Attribute uid = attrs.get("uid");
        if (uid != null) {
          result.add( getCitizen((String)uid.get()) );
        }
      }
     
      return (Citizen[])result.toArray(new Citizen[result.size()]);

    } catch (Exception e) {
      _zone.log().error("LDAPRealm.searchCitizenByVariable() failed: "+e);
     
    } finally {
      cleanupContext(connImpl);
    }
    return null;
  }

 
  public Citizen getAnonymousCitizen()
  {
    return null;
  }
 

  public Tribe getRoot()
  {
    if (_rootTribe == null) {
      synchronized(this) {
        if (_rootTribe == null) {
          try {
            _rootTribe = new LDAPTribe(this, ROOT_TRIBE, true);
          } catch(OperationFailedException e) {
            _zone.log().error("LDAPRealm.getRoot(): "+e);
          }
        }
      }
    }
   
    return _rootTribe;
  }


  Tribe[] getMemberGroups(String dn)
  {
    PooledConnection connImpl = null;
    DirContext ctx = null;
    List groups = new ArrayList();
 
    try {
      connImpl = _manager.acquire(_contextPool);
      ctx = (DirContext)connImpl.getConnection();
     
      NamingEnumeration enu = null;
      SearchControls sc = new SearchControls();
      sc.setReturningAttributes(new String[] {"cn"});
     
      enu = ctx.search("ou=groups", "(uniqueMember="+ dn +")", sc);
 
      while (enu.hasMore()) {
        SearchResult s = (SearchResult)enu.next();
        Attributes a = s.getAttributes();
        Attribute cn = a.get("cn");
        if (cn != null) {
          groups.add( getTribe((String)cn.get()) );
        }
      }
      return (Tribe[])groups.toArray(new Tribe[groups.size()]);

    } catch (Exception e) {
      _zone.log().error("LDAPRealm.getMemberGroups() error: "+e);
     
    } finally {
      cleanupContext(connImpl);
    }
   
    return null;
  }
 
 
  public Tribe createTribe(String name) throws OperationFailedException {
    if (name == null) throw new OperationFailedException("Null tribe name!");
   
    PooledConnection connImpl = null;
    DirContext ctx = null;
 
    try {
      connImpl = _manager.acquire(_contextPool);
      ctx = (DirContext)connImpl.getConnection();
     
      Attributes at = new BasicAttributes();
      at.put(groupObjectClass);
     
      at.put("cn", name);
     
      ctx.bind("cn="+name+",ou=groups", null, at);
     
      //"refresh" root tribe
      if (_rootTribe != null) {
        _rootTribe.refreshCitizens();
      }

      return (Tribe)getTribe(name);
     
    } catch (NameAlreadyBoundException e) {
      throw new OperationFailedException("Group '"+name+"' already exists!");

    } catch (Exception e) {
      _zone.log().error("LDAPRealm.createTribe(): "+e);
     
    } finally {
      cleanupContext(connImpl);
    }

    return null;
  }
 
 
  public Citizen createCitizen(String username, String password) throws OperationFailedException {
    return createCitizen(username, password, null);
  }
 

  public Citizen createCitizen(String username, String password, String[][] params) throws OperationFailedException
  {
    if (username == null) throw new OperationFailedException("Null username!");
    username = username.trim().toLowerCase();
    if (!checkEmail(username)) throw new OperationFailedException("Username isn't a valid email address!");
   
    PooledConnection connImpl = null;
    DirContext ctx = null;
 
    try {
      connImpl = _manager.acquire(_contextPool);
      ctx = (DirContext)connImpl.getConnection();
     
      Attributes at = new BasicAttributes();
      at.put("facsimileTelephoneNumber", password);
      at.put(objectClassAttr);
     
      Array others = new Array();
      if (params != null) {
        for (int i=0,l=params.length; i<l; i++) {
          String key = params[i][0];
          String val = params[i][1];
 
          if (LDAPCitizen.ATTRMAP_C.containsKey(key)) {
            at.put((String)LDAPCitizen.ATTRMAP_C.get(key), val);
            //System.err.println ("Save: OK attr: "+LDAPCitizen.ATTRMAP_C.get(key)+" = "+val);
          } else {
            others.put(Any.create(key), Any.create(val));
            //System.err.println ("Save: Unknown attr: "+LDAPCitizen.ATTRMAP_C.get(key)+" = "+val);
          }
        }
      }
     
      at.put("cn", username);
      if (at.get("sn") == null) {
        at.put("sn", username);
      }
      if (others.size() > 0) {
        try {
          String sothers = Serialization.serialize(null, others);
          at.put(LDAPCitizen.OTHERS_ATTR, sothers);
        } catch(IOException ioe) {
          throw new OperationFailedException("Data serialization failed: "+ioe);
        }
      }
     
      ctx.bind("uid="+username+",ou=users", null, at);
     
      //"refresh" root tribe
      if (_rootTribe != null) {
        _rootTribe.refreshCitizens();
      }

      return (Citizen)getCitizen(username);
     
    } catch (NameAlreadyBoundException e) {
      throw new OperationFailedException("User '"+username+"' already exists!");

    } catch (Exception e) {
      _zone.log().error("LDAPRealm.createCitizen(): "+e);
     
    } finally {
      cleanupContext(connImpl);
    }

    return null;
  }
 

  public void setRoot(Tribe tribe) throws OperationFailedException
  {
    throw new OperationFailedException("This implementation doesn't support setting of root tribe!");
  }


  void removeCitizen(String username)
  {
    if (_users.containsKey(username)) {
      _users.remove(username);

      if (_rootTribe != null) {
        _rootTribe.refreshCitizens();
      }
    }
  }

  PooledConnection getConnection() throws Exception
  {
    return _manager.acquire(_contextPool);
  }
 
 
  Log getLog()
  {
    return _zone.log();
  }

 
  static void cleanupContext(PooledConnection connImpl)
  {
    if (connImpl != null) {
      connImpl.release();
    }
  }


  public String getPrefix() {
    return _prefix;
  }
 
 
  public String createUserDN(String name) {
    StringBuffer buf = new StringBuffer();
    buf.append("uid=");
    buf.append(name);
    buf.append(",ou=users");
    if (_prefix != null && _prefix.length() > 0) {
      buf.append(",");
      buf.append(_prefix);
    }
    return buf.toString();
  }

 
  public String createGroupDN(String name) {
    StringBuffer buf = new StringBuffer();
    buf.append("cn=");
    buf.append(name);
    buf.append(",ou=groups");
    if (_prefix != null && _prefix.length() > 0) {
      buf.append(",");
      buf.append(_prefix);
    }
    return buf.toString();
  }

 
  private boolean checkEmail(String email)
  {
    return new Perl5Matcher().matches(email, EMAIL_PATTERN);
  }


  PermissionCollection loadPermissions(String dn) {
    PooledConnection connImpl = null;
    DirContext ctx = null;
 
    try {
      connImpl = getConnection();
      ctx = (DirContext)connImpl.getConnection();
      return loadPermissions(ctx, dn);
 
    } catch (Exception e) {
      _zone.log().error("LDAPRealm.loadPermissions(): "+e);
     
    } finally {
      cleanupContext(connImpl);
    }
    return null;
  }
 

  static PermissionCollection loadPermissions(DirContext ctx, String dn) throws Exception {
    Permissions result = new Permissions();
    Attributes attrs = ctx.getAttributes(dn, new String[] { "description" });
    Attribute desc = attrs.get("description");
    if (desc != null) {
      for (int i=0, l=desc.size(); i<l; i++) {
        try {
          String[] permSt = parsePermission((String)desc.get(i));
          result.add( PolicyPreferences.createPermission(permSt) );
        } catch(Throwable t) {
          throw new OperationFailedException("LDAPRealm.loadPermissions(): "+t.getMessage());
        }
      }
    }
    return result;
  }
 
 
  PermissionCollection addPermission(Permission perm, String dn) throws OperationFailedException {
    PooledConnection connImpl = null;
    DirContext ctx = null;
 
    try {
      connImpl = getConnection();
      ctx = (DirContext)connImpl.getConnection();

      PermissionCollection storage = LDAPRealm.loadPermissions(ctx, dn);
      boolean found = false;
      for (Enumeration enu=storage.elements(); enu.hasMoreElements(); ) {
        if (perm.equals(enu.nextElement())) {
          _zone.log().error("--addPermission() we already have: "+perm);
          found = true;
        }
      }
      storage.add(perm);
      if (!found) {
        LDAPRealm.savePermissions(ctx, dn, storage);
        _zone.log().error("--addPermissions() perm added: "+perm);
      }
      return storage;
 
    } catch (Exception e) {
      throw new OperationFailedException(e.getMessage());
     
    } finally {
      cleanupContext(connImpl);
    }
  }


  PermissionCollection removePermission(Permission perm, String dn) throws OperationFailedException {
    PooledConnection connImpl = null;
    DirContext ctx = null;
 
    try {
      connImpl = getConnection();
      ctx = (DirContext)connImpl.getConnection();

      PermissionCollection storage = LDAPRealm.loadPermissions(ctx, dn);
      PermissionCollection altered = new Permissions();
     
      boolean found = false;
      for (Enumeration enu=storage.elements(); enu.hasMoreElements(); ) {
        Permission p = (Permission)enu.nextElement();
        if (perm.equals(p)) {
          found = true;
        } else {
          altered.add(p);
        }
      }
      if (found) {
        LDAPRealm.savePermissions(ctx, dn, altered);
        _zone.log().error("--removePermissions() perm removed: "+altered);
      } else {
        _zone.log().error("--removePermissions() kusee.."+altered);
      }
      return altered;
 
    } catch (Exception e) {
      throw new OperationFailedException(e.getMessage());
     
    } finally {
      cleanupContext(connImpl);
    }
  }


  static void savePermissions(DirContext ctx, String dn, PermissionCollection perms) throws Exception {
    Attribute attr = new BasicAttribute("description");
    Attributes attrs = new BasicAttributes();
    for (Enumeration enu=perms.elements(); enu.hasMoreElements(); ) {
      attr.add( createPermissionString((Permission)enu.nextElement()) );
    }
    attrs.put(attr);
    ctx.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs);
  }
 
 
  static String createPermissionString(Permission p) {
    StringBuffer b = new StringBuffer();
    String type = p.getClass().getName();
    String tmp = null;
   
    if (type.equals("anvil.core.ToolPermission")) {
      b.append("tool");

    } else if (type.equals("anvil.core.RuntimePermission")) {
      b.append("runtime");

    } else if (type.equals("java.io.FilePermission")) {
      b.append("file");

    } else if (type.equals("java.net.SocketPermission")) {
      b.append("socket");

    } else if (type.equals("anvil.java.security.JavaPermission")) {
      b.append("java");

    } else if (type.equals("anvil.database.ConnectionPoolPermission")) {
      b.append("pool");

    } else if (type.equals("anvil.script.ImportPermission")) {
      b.append("import");

    } else if (type.equals("anvil.server.RealmPermission")) {
      b.append("realm");

    } else if (type.equals("anvil.server.NamespacePermission")) {
      b.append("namespace");

    } else if (type.equals("java.security.AllPermission")) {
      b.append("all");

    } else {
      b.append(type);
    }
    b.append("|");
   
    if ((tmp = p.getName()) != null) {
      b.append(tmp);
    }
    b.append("|");
   
    if ((tmp = p.getActions()) != null) {
      b.append(tmp);
    }
    return b.toString();
  }
 

  static String[] parsePermission(String s)
  {
    StringTokenizer st = new StringTokenizer(s, "|");
    int len = st.countTokens();
    if (len < 2 || len > 3) return null;
    String[] res = new String[len];
    for (int i=0; i<len; i++) {
      res[i] = st.nextToken();
    }
    return res;
  }

 
}
TOP

Related Classes of anvil.server.ldap.LDAPRealm

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.