1
2
3
4
5
6
7 package gov.bnl.gums.account;
8
9 import gov.bnl.gums.GUMS;
10 import gov.bnl.gums.SiteUser;
11 import gov.bnl.gums.configuration.Configuration;
12 import gov.bnl.gums.util.CertToolkit;
13 import gov.bnl.gums.util.GecosMap;
14
15 import java.util.Hashtable;
16 import java.util.Map;
17 import java.util.Properties;
18
19 import javax.naming.NamingEnumeration;
20 import javax.naming.directory.Attribute;
21 import javax.naming.directory.Attributes;
22 import javax.naming.directory.DirContext;
23 import javax.naming.directory.InitialDirContext;
24 import javax.naming.directory.SearchResult;
25 import javax.persistence.Entity;
26 import javax.persistence.Transient;
27
28 import org.apache.log4j.Logger;
29
30
31
32
33
34
35
36 @Entity
37 public class GecosNisAccountMapper extends AccountMapper {
38 static private Logger log = Logger.getLogger(GecosNisAccountMapper.class);
39 static Logger gumsAdminLog = Logger.getLogger(GUMS.gumsAdminLogName);
40 static private Map<String, GecosMap> gecosMaps = new Hashtable<String, GecosMap>();
41
42
43 private String jndiNisUrl;
44 private String accountField = "cn";
45 private String gecosField = "gecos";
46
47 public GecosNisAccountMapper() {
48 super();
49 gumsAdminLog.debug("The use of gov.bnl.gums.GecosNisAccountMapper is unsupported.");
50 }
51
52 public GecosNisAccountMapper(Configuration configuration, String name) {
53 super(configuration, name);
54 }
55
56 public GecosMap createMap() {
57 Properties jndiProperties = retrieveJndiProperties();
58 int nTries = 5;
59 Exception lastException = null;
60 int i = 0;
61 for (; i < nTries; i++) {
62 GecosMap map = new GecosMap();
63 log.debug("Attempt " + i + " to retrieve map for '" + jndiNisUrl + "'");
64 try {
65 DirContext jndiCtx = new InitialDirContext(jndiProperties);
66 NamingEnumeration<SearchResult> nisMap = jndiCtx.search("system/passwd.byname", "(cn=*)", null);
67 log.trace("Server responded");
68 while (nisMap.hasMore()) {
69 SearchResult res = (SearchResult) nisMap.next();
70 Attributes atts = res.getAttributes();
71 String account = (String) atts.get(accountField).get();
72 Attribute gecosAtt = atts.get(gecosField);
73 if (gecosAtt != null) {
74 String gecos = gecosAtt.get().toString();
75 map.addEntry(account, gecos);
76 } else {
77 log.trace("Found user '" + account + "' with no GECOS field");
78 }
79 }
80 jndiCtx.close();
81 return map;
82 } catch (javax.naming.NamingException ne) {
83 log.warn("Error filling the maps for NIS "+jndiNisUrl, ne);
84 lastException = ne;
85 try {
86 Thread.sleep(100);
87 } catch (InterruptedException e) {
88 log.warn("Interrupted", e);
89 }
90 } catch (Exception e) {
91 log.warn("Error filling the maps for NIS "+jndiNisUrl, e);
92 lastException = e;
93 try {
94 Thread.sleep(100);
95 } catch (InterruptedException ie) {
96 log.warn("Interrupted", e);
97 }
98 }
99 }
100 if (i == nTries) {
101 throw new RuntimeException("Couldn't retrieve NIS maps from " + jndiNisUrl, lastException);
102 }
103 return null;
104 }
105
106 public String getAccountField() {
107 return accountField;
108 }
109
110 public String getGecosField() {
111 return gecosField;
112 }
113
114 public String getJndiNisUrl() {
115 return jndiNisUrl;
116 }
117
118 public SiteUser mapDn(String dn, boolean createIfDoesNotExist) {
119 String[] nameSurname = CertToolkit.parseNameAndSurname(dn);
120 GecosMap map = gecosMap();
121 log.trace("GECOS findAccount. Name: " + nameSurname[0] + " - Surname: " + nameSurname[1] + " - GECOSMap: " + gecosMap());
122 return new SiteUser(map.findAccount(nameSurname[0], nameSurname[1]));
123 }
124
125 @ConfigFieldAnnotation(label="NIS Account UID Field", example="uid")
126 public void setAccountField(String accountField) {
127 this.accountField = accountField;
128 }
129
130 @ConfigFieldAnnotation(label="NIS Name Field", example="gecos")
131 public void setGecosField(String gecosField) {
132 this.gecosField = gecosField;
133 }
134
135 @ConfigFieldAnnotation(label="JNDI NIS URL", example="nis://localhost/usatlas.bnl.gov ")
136 public void setJndiNisUrl(String jndiNisUrl) {
137 this.jndiNisUrl = jndiNisUrl;
138 }
139
140 private GecosMap gecosMap() {
141 synchronized (gecosMaps) {
142 GecosMap map = (GecosMap) gecosMaps.get(getMapName());
143 if (map != null) {
144 if (map.isValid()) {
145 log.trace("Reusing GECOS map for '" + getMapName() +"'");
146 return map;
147 } else {
148 log.trace("Invalidating expired GECOS map for '" + getMapName() +"'");
149 gecosMaps.remove(getMapName());
150 }
151 }
152 log.debug("Creating new GECOS map for '" + getMapName() + "'");
153 map = createMap();
154 gecosMaps.put(getMapName(), map);
155 return map;
156 }
157 }
158
159 private Properties retrieveJndiProperties() {
160 Properties jndiProperties = new java.util.Properties();
161 jndiProperties.put("java.naming.provider.url", jndiNisUrl);
162 jndiProperties.put("java.naming.factory.initial","com.sun.jndi.nis.NISCtxFactory");
163 return jndiProperties;
164 }
165
166 @Transient
167 protected String getMapName() {
168 return jndiNisUrl;
169 }
170 }