001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.console.ldapmanager;
017:
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.Enumeration;
021: import java.util.HashMap;
022: import java.util.Hashtable;
023: import java.util.List;
024: import java.util.Map;
025:
026: import javax.naming.Context;
027: import javax.naming.NameClassPair;
028: import javax.naming.NamingEnumeration;
029: import javax.naming.NamingException;
030: import javax.naming.directory.Attribute;
031: import javax.naming.directory.Attributes;
032: import javax.naming.directory.DirContext;
033: import javax.naming.directory.InitialDirContext;
034: import javax.naming.directory.SearchControls;
035: import javax.naming.directory.SearchResult;
036: import javax.servlet.http.HttpSession;
037:
038: import org.directwebremoting.annotations.RemoteMethod;
039: import org.directwebremoting.annotations.RemoteProxy;
040:
041: import uk.ltd.getahead.dwr.WebContext;
042: import uk.ltd.getahead.dwr.WebContextFactory;
043:
044: /**
045: * The LDAP manager helper
046: */
047: @RemoteProxy(name="LDAPHelper")
048: public class LDAPManagerHelper {
049: private final static String LDAP_VERSION_KEY = "java.naming.ldap.version";
050:
051: private final static String SSL_VALUE = "ssl";
052:
053: private final static String NONE_VALUE = "none";
054:
055: private final static String INITIAL_CONTEXT_FACTORY_DEFAULT = "com.sun.jndi.ldap.LdapCtxFactory";
056:
057: private final static String HOST_DEFAULT = "localhost";
058:
059: private final static String PORT_DEFAULT = "1389";
060:
061: private final static String BASE_DN_DEFAULT = "ou=system";
062:
063: // LDAP Version: "3", "2"
064: private final static String LDAP_VERSION_DEFAULT = "3";
065:
066: // Security Protocol: "simple", "ssl", "sasl"
067: private final static String SECURITY_PROTOCOL_DEFAULT = "simple";
068:
069: // Security Authentication: "simple", "none", "strong"
070: private final static String SECURITY_AUTHENTICATION_DEFAULT = "simple";
071:
072: private final static String SECURITY_PRINCIPAL_DEFAULT = "uid=admin, ou=system";
073:
074: private final static String SECURITY_CREDENTIALS_DEFAULT = "secret";
075:
076: private final static String ONELEVEL_SCOPE = "onelevel";
077:
078: private final static String SUBTREE_SCOPE = "subtree";
079:
080: private final static String DIR_CONTEXT_KEY = "LDAPManagerHelper.dirContext";
081:
082: private final static String DIR_ENV_KEY = "LDAPManagerHelper.dirEnv";
083:
084: private final static String HOST_KEY = "LDAPManagerHelper.host";
085:
086: private final static String PORT_KEY = "LDAPManagerHelper.port";
087:
088: private final static String BASE_DN_KEY = "LDAPManagerHelper.baseDN";
089:
090: private final static String SUCCESS_RESULT = "<SUCCESS>";
091:
092: private DirContext dirContext;
093:
094: private Hashtable dirEnv;
095:
096: private String host;
097:
098: private String port;
099:
100: private String baseDN;
101:
102: /**
103: * Construct an LDAP manager helper using config data (default)
104: */
105: public LDAPManagerHelper() throws Exception {
106: dirContext = (DirContext) getSessionAttribute(DIR_CONTEXT_KEY);
107: if (dirContext != null) {
108: dirEnv = (Hashtable) getSessionAttribute(DIR_ENV_KEY);
109: host = (String) getSessionAttribute(HOST_KEY);
110: port = (String) getSessionAttribute(PORT_KEY);
111: baseDN = (String) getSessionAttribute(BASE_DN_KEY);
112: }
113: }
114:
115: /**
116: * Construct an LDAP manager helper using config data (partial)
117: */
118: public LDAPManagerHelper(String host, String port, String baseDN,
119: String securityAuthentication, String userDN, String userPwd)
120: throws Exception {
121: connect(INITIAL_CONTEXT_FACTORY_DEFAULT, host, port, baseDN,
122: LDAP_VERSION_DEFAULT, SECURITY_PROTOCOL_DEFAULT,
123: securityAuthentication, userDN, userPwd);
124: }
125:
126: /**
127: * Construct an LDAP manager helper using config data (all)
128: */
129: public LDAPManagerHelper(String initialContextFactory, String host,
130: String port, String baseDN, String ldapVersion,
131: String securityProtocol, String securityAuthentication,
132: String securityPrincipal, String securityCredentials)
133: throws Exception {
134: connect(initialContextFactory, host, port, baseDN, ldapVersion,
135: securityProtocol, securityAuthentication,
136: securityPrincipal, securityCredentials);
137: }
138:
139: /**
140: * Create a directory context using config data
141: */
142: @RemoteMethod
143: public synchronized String connect(String initialContextFactory,
144: String host, String port, String baseDN,
145: String ldapVersion, String securityProtocol,
146: String securityAuthentication, String securityPrincipal,
147: String securityCredentials) throws Exception {
148: String result = SUCCESS_RESULT;
149:
150: Hashtable dirEnv = new Hashtable();
151: dirEnv.put(Context.INITIAL_CONTEXT_FACTORY,
152: initialContextFactory);
153: String providerURL = createLDAPURL(host, port, ""); // Empty Base DN
154: dirEnv.put(Context.PROVIDER_URL, providerURL);
155: dirEnv.put(LDAP_VERSION_KEY, ldapVersion);
156: if (SSL_VALUE.equalsIgnoreCase(securityProtocol)) {
157: dirEnv.put(Context.SECURITY_PROTOCOL, SSL_VALUE);
158: }
159: dirEnv.put(Context.SECURITY_AUTHENTICATION,
160: securityAuthentication);
161: if (!(NONE_VALUE.equalsIgnoreCase(securityAuthentication))) {
162: // Either "simple" or "strong"
163: dirEnv.put(Context.SECURITY_PRINCIPAL, securityPrincipal); // User DN
164: dirEnv.put(Context.SECURITY_CREDENTIALS,
165: securityCredentials); // Password
166: }
167:
168: try {
169: DirContext newDirContext = new InitialDirContext(dirEnv);
170: // Close old context
171: if (dirContext != null) {
172: dirContext.close();
173: }
174: // Save directory data to class vars
175: this .dirContext = newDirContext;
176: this .dirEnv = dirEnv;
177: this .host = host;
178: this .port = port;
179: this .baseDN = baseDN;
180: // Save directory data to session
181: setSessionAttribute(DIR_CONTEXT_KEY, dirContext);
182: setSessionAttribute(DIR_ENV_KEY, dirEnv);
183: setSessionAttribute(HOST_KEY, host);
184: setSessionAttribute(PORT_KEY, port);
185: setSessionAttribute(BASE_DN_KEY, baseDN);
186: } catch (NamingException e) {
187: result = "Problem connecting to directory server: "
188: + e.getMessage();
189: }
190:
191: return result;
192: }
193:
194: /**
195: * Return directory context environment
196: */
197: @RemoteMethod
198: public Map getEnvironment() {
199: Map env = new HashMap();
200: env.put("host", host);
201: env.put("port", port);
202: String ldapVersion = (String) dirEnv.get(LDAP_VERSION_KEY);
203: env.put("ldapVersion", ldapVersion);
204: env.put("baseDN", baseDN);
205: String securityProtocol = (String) dirEnv
206: .get(Context.SECURITY_PROTOCOL);
207: env.put("securityProtocol", securityProtocol);
208: String securityAuthentication = (String) dirEnv
209: .get(Context.SECURITY_AUTHENTICATION);
210: env.put("securityAuthentication", securityAuthentication);
211: String securityPrincipal = (String) dirEnv
212: .get(Context.SECURITY_PRINCIPAL);
213: env.put("securityPrincipal", securityPrincipal);
214:
215: return env;
216: }
217:
218: /**
219: * Returns the names bound in the named context
220: */
221: @RemoteMethod
222: public Collection list(String name) throws Exception {
223: ArrayList result = new ArrayList();
224:
225: if (dirContext == null) {
226: return result;
227: }
228:
229: try {
230: NamingEnumeration list = dirContext.list(name); // can't be ""
231:
232: while (list.hasMore()) {
233: NameClassPair ncp = (NameClassPair) list.next();
234: String childName = ncp.getName();
235: String dn = childName + ", " + name;
236: String[] pair = { childName, dn };
237: result.add(pair);
238: }
239: } catch (NamingException e) {
240: throw new Exception("Problem getting directory list: "
241: + e.getMessage());
242: }
243:
244: return result;
245: }
246:
247: /**
248: * Returns the names bound in the base DN context
249: */
250: public Collection listBaseDN() throws Exception {
251: return list(baseDN);
252: }
253:
254: /**
255: * Enumerates the names bound in the named context and return result as JSON
256: */
257: public String listJSON(String name) throws Exception {
258: return listJSON(name, null);
259: }
260:
261: /**
262: * Enumerates the names bound in the named context and return result as JSON
263: */
264: public String listJSON(String name, String commonFields)
265: throws Exception {
266: // JSON: [{title:"Title1",isFolder:true}, {title:"Title2"}]
267:
268: StringBuffer json = new StringBuffer();
269: List list = (List) list(name);
270:
271: json.append('[');
272: int size = list.size();
273: for (int i = 0; i < size; i++) {
274: String[] entry = (String[]) list.get(i);
275: json.append("{title:\"");
276: json.append(entry[0]);
277: json.append("\",widgetId:\"");
278: json.append(entry[1]);
279: json.append("\"");
280: if (commonFields != null) { // TODO: Do additional testing
281: json.append(commonFields);
282: }
283: json.append("}");
284: if ((i + 1) < size) {
285: json.append(',');
286: }
287: }
288: json.append("]");
289:
290: return json.toString();
291: }
292:
293: /**
294: * Return the attributes of an LDAP entry
295: */
296: @RemoteMethod
297: public Collection getAttributes(String name) throws Exception {
298: ArrayList result = new ArrayList();
299:
300: if (dirContext == null) {
301: return result;
302: }
303:
304: try {
305: Attributes attribs = dirContext.getAttributes(name);
306: NamingEnumeration attributes = attribs.getAll();
307: while (attributes.hasMore()) {
308: Attribute attribute = (Attribute) attributes.next();
309: String id = attribute.getID();
310: NamingEnumeration values = attribute.getAll();
311: while (values.hasMore()) {
312: String value = values.next().toString();
313: String[] pair = { id, value };
314: result.add(pair);
315: }
316: }
317: } catch (NamingException e) {
318: throw new Exception("Problem retrieving attributes: "
319: + e.getMessage());
320: }
321: return result;
322: }
323:
324: /**
325: * Execute an LDAP search
326: */
327: @RemoteMethod
328: public Collection search(String searchDN, String filter,
329: String searchScope) throws Exception {
330: ArrayList result = new ArrayList();
331:
332: if (dirContext == null) {
333: return result;
334: }
335:
336: try {
337: String ldapURL = createLDAPURL(host, port, searchDN);
338: SearchControls sc = new SearchControls();
339: if (ONELEVEL_SCOPE.equalsIgnoreCase(searchScope)) {
340: sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
341: } else if (SUBTREE_SCOPE.equalsIgnoreCase(searchScope)) {
342: sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
343: } else {
344: // Default to one level scope
345: sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
346: }
347: // Filter: "(objectclass=*)"
348: boolean isSearchDNAdded = false;
349: NamingEnumeration ne = dirContext.search(ldapURL, filter,
350: sc);
351: while (ne.hasMore()) {
352: SearchResult sr = (SearchResult) ne.next();
353: String name = sr.getName();
354: String dn = null;
355: if (name.length() > 0) {
356: dn = name + "," + searchDN;
357: result.add(dn);
358: } else if ((name.length() == 0) && !isSearchDNAdded) {
359: dn = searchDN;
360: result.add(dn);
361: isSearchDNAdded = true;
362: }
363: }
364: } catch (NamingException e) {
365: throw new Exception("Problem performing directory search: "
366: + e.getMessage());
367: }
368: return result;
369: }
370:
371: /**
372: * Close directory context
373: */
374: public void close() throws Exception {
375: if (dirContext != null) {
376: try {
377: dirContext.close();
378: dirContext = null;
379: } catch (NamingException e) {
380: throw new Exception(
381: "Problem closing directory context: "
382: + e.getMessage());
383: }
384: }
385: }
386:
387: /**
388: * Return base DN of this directory context
389: */
390: @RemoteMethod
391: public String getBaseDN() {
392: return baseDN;
393: }
394:
395: /**
396: * Create an LDAP url using host, port, and base DN
397: */
398: private String createLDAPURL(String host, String port, String baseDN) {
399: StringBuffer url = new StringBuffer();
400: url.append("ldap://");
401: url.append(host);
402: url.append(':');
403: url.append(port);
404: if ((baseDN != null) && (baseDN.length() >= 3)) {
405: if (!baseDN.startsWith("/")) {
406: url.append('/');
407: }
408: url.append(baseDN);
409: }
410: return url.toString();
411: }
412:
413: /**
414: * Get the HTTP session
415: */
416: private HttpSession getSession() {
417: WebContext ctx = WebContextFactory.get();
418: HttpSession session = ctx.getSession();
419: return session;
420: }
421:
422: /**
423: * Set an HTTP session attribute
424: */
425: private void setSessionAttribute(String name, Object value) {
426: getSession().setAttribute(name, value);
427: }
428:
429: /**
430: * Get an HTTP session attribute
431: */
432: private Object getSessionAttribute(String name) {
433: return getSession().getAttribute(name);
434: }
435:
436: /**
437: * Dump HTTP session attributes
438: */
439: private void dumpSession() {
440: System.out.println("--- dumpSession()");
441: WebContext ctx = WebContextFactory.get();
442: HttpSession session = ctx.getSession();
443: Enumeration attribNames = session.getAttributeNames();
444: while (attribNames.hasMoreElements()) {
445: String attribName = (String) attribNames.nextElement();
446: System.out.print("--- session: " + attribName + " = ");
447: Object attribValue = session.getAttribute(attribName);
448: System.out.println(attribValue);
449: }
450: }
451:
452: /**
453: * Dump search enumeration
454: */
455: private void printSearchEnumeration(NamingEnumeration ne) {
456: try {
457: while (ne.hasMore()) {
458: SearchResult sr = (SearchResult) ne.next();
459: System.out.println("-->" + sr.getName());
460: System.out.println(sr.getAttributes());
461: }
462: } catch (NamingException e) {
463: e.printStackTrace();
464: }
465: }
466:
467: }
|