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