View Javadoc

1   /*
2    * NISAccountMapper.java
3    *
4    * Created on May 25, 2004, 2:25 PM
5    */
6   
7   package gov.bnl.gums.account;
8   
9   import gov.bnl.gums.GUMS;
10  import gov.bnl.gums.configuration.Configuration;
11  
12  import java.util.*;
13  
14  import javax.naming.Context;
15  import javax.naming.NamingEnumeration;
16  import javax.naming.directory.Attribute;
17  import javax.naming.directory.Attributes;
18  import javax.naming.directory.DirContext;
19  import javax.naming.directory.InitialDirContext;
20  import javax.naming.directory.SearchResult;
21  
22  import org.apache.commons.logging.*;
23  
24  /** 
25   * Maps a user to a local account based on the CN of the certificate and the
26   * gecos field in the NIS/YP database. The mapping can't be perfect, but contains
27   * a series of heuristics that solve up to 90% of the cases, depending on how
28   * the NIS database itself is kept.
29   * <p>
30   * It's suggested not to use this policy by itself, but to have it part of a 
31   * CompositeAccountMapper in which a ManualAccountMapper comes first. This allows
32   * to override those user mapping that are not satisfying.
33   *
34   * @author Jay Packard
35   */
36  public class LdapAccountMapper extends AccountMapper {
37      static private Log log = LogFactory.getLog(LdapAccountMapper.class);
38  	static public String getTypeStatic() {
39  		return "ldap";
40  	}
41      private String jndiLdapUrl = "";
42  	private String dnField = "description";
43  	private String accountField = "uid";
44      
45      public LdapAccountMapper() {
46      	super();
47      }
48      
49      public LdapAccountMapper(Configuration configuration) {
50      	super(configuration);
51      }
52      
53      public LdapAccountMapper(Configuration configuration, String name) {
54      	super(configuration, name);
55      }
56      
57      public AccountMapper clone(Configuration configuration) {
58      	LdapAccountMapper accountMapper = new LdapAccountMapper(configuration, new String(getName()));
59      	accountMapper.setDescription(new String(getDescription()));
60      	accountMapper.setJndiLdapUrl(new String(jndiLdapUrl));
61      	accountMapper.setDnField(new String(dnField));
62      	accountMapper.setAccountField(new String(accountField));
63      	return accountMapper;
64      }
65      
66      public String getAccountField() {
67          return accountField;
68      }
69      
70      public String getDnField() {
71          return dnField;
72      }
73      
74      public String getJndiLdapUrl() {
75          return jndiLdapUrl;
76      }
77      
78      public String getType() {
79  		return "ldap";
80  	}
81      
82      public String mapUser(String userDN, boolean createIfDoesNotExist) {
83      	Properties jndiProperties = retrieveJndiProperties();
84      	String userDNWithSubject = "subject="+userDN;
85          int nTries = 5;
86          int i = 0;
87          for (; i < nTries; i++) {
88              log.debug("Attempt " + i + " to retrieve map at '" + jndiLdapUrl + "'");
89              try {
90                  DirContext jndiCtx = new InitialDirContext(jndiProperties);
91                  NamingEnumeration nisMap = jndiCtx.search("ou=People", "(cn=*)", null);
92                  log.debug("Server responded");
93                  while (nisMap.hasMore()) {
94                      SearchResult res = (SearchResult) nisMap.next();
95                      Attributes atts = res.getAttributes();
96                      Attribute dnAtt = atts.get(dnField);
97                      if (dnAtt != null) {
98                          String dn = dnAtt.get().toString();
99                          if (userDN.equals(dn) || userDNWithSubject.equals(dn)) {
100 	                        String account = (String) atts.get(accountField).get();
101 	                        log.debug("Found account '" + account + "' for DN '" + userDN + "'");
102 	                        return account;
103                         }
104                     }
105                 }
106                 jndiCtx.close();
107             } catch (javax.naming.NamingException ne) {
108                 log.warn("Error searching LDAP at "+jndiLdapUrl, ne);
109                 try {
110                     Thread.sleep(100);
111                 } catch (InterruptedException e) {
112                     log.warn("Interrupted", e);
113                 }
114             } catch (Exception e) {
115                 log.warn("Error searching LDAP at "+jndiLdapUrl, e);
116                 try {
117                     Thread.sleep(100);
118                 } catch (InterruptedException ie) {
119                     log.warn("Interrupted", e);
120                 }
121             }
122         }
123         return null;       
124     }
125 
126     public void setAccountField(String accountField) {
127         this.accountField = accountField;
128     }
129     
130     public void setDnField(String dnField) {
131         this.dnField = dnField;
132     }
133     
134     public void setJndiLdapUrl(String jndiLdapUrl) {
135         this.jndiLdapUrl = jndiLdapUrl;
136     }
137 
138     public String toString(String bgColor) {
139     	return "<td bgcolor=\""+bgColor+"\"><a href=\"accountMappers.jsp?command=edit&name=" + getName() + "\">" + getName() + "</a></td><td bgcolor=\""+bgColor+"\">" + getType() + "</td><td bgcolor=\""+bgColor+"\">&nbsp;</td>";
140     }
141 
142     public String toXML() {
143     	return "\t\t<ldapAccountMapper\n"+
144 			"\t\t\tname='"+getName()+"'\n"+
145 			"\t\t\tdescription='"+getDescription()+"'\n"+
146 			"\t\t\tjndiLdapUrl='"+jndiLdapUrl+"'\n"+
147 			"\t\t\tdnField='"+dnField+"'\n"+
148 			"\t\t\taccountField='"+accountField+"'/>\n\n";
149     }
150     
151     private Properties retrieveJndiProperties() {
152         Properties jndiProperties = new java.util.Properties();
153         jndiProperties.put("java.naming.provider.url", jndiLdapUrl);
154         jndiProperties.put("java.naming.factory.initial","com.sun.jndi.ldap.LdapCtxFactory");
155         jndiProperties.put(Context.SECURITY_PROTOCOL, "none");
156         return jndiProperties;
157     } 
158 }