001: /**
002: * $Id: LDAPABApplicationHelper.java,v 1.33 2005/09/21 10:40:12 dg154973 Exp $
003: * Copyright 2002 Sun Microsystems, Inc. All rights reserved. Use of this
004: * product is subject to license terms. Federal Acquisitions: Commercial
005: * Software -- Government Users Subject to Standard License Terms and
006: * Conditions. Sun, Sun Microsystems, the Sun logo, and iPlanet are trademarks
007: * or registered trademarks of Sun Microsystems, Inc. in the United States and
008: * other countries.
009: */package com.sun.portal.providers.ab;
010:
011: import java.io.BufferedReader;
012: import java.io.InputStreamReader;
013: import java.io.IOException;
014: import java.io.UnsupportedEncodingException;
015: import java.net.MalformedURLException;
016: import java.net.HttpURLConnection;
017: import java.net.URL;
018: import java.net.URLEncoder;
019: import java.util.Date;
020: import java.util.Enumeration;
021: import java.util.Properties;
022: import java.util.Hashtable;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Map.Entry;
026: import java.util.Set;
027: import java.util.StringTokenizer;
028: import java.util.Iterator;
029: import java.util.ResourceBundle;
030: import java.util.logging.Logger;
031: import java.util.logging.Level;
032: import javax.mail.MessagingException;
033: import javax.mail.AuthenticationFailedException;
034: import javax.mail.Store;
035: import javax.servlet.http.HttpServletRequest;
036: import javax.servlet.http.HttpServletResponse;
037: import com.sun.ssoadapter.SSOAdapter;
038: import com.sun.ssoadapter.SSOAdapterException;
039: import com.sun.ssoadapter.SSOAdapterFactory;
040: import com.sun.portal.providers.ProviderEditUtility;
041: import com.sun.addressbook.ABStore;
042: import com.sun.addressbook.ABStoreException;
043: import com.sun.addressbook.ABSession;
044: import com.iplanet.am.sdk.AMException;
045: import com.iplanet.am.sdk.AMStoreConnection;
046: import com.iplanet.am.sdk.AMUser;
047: import com.iplanet.sso.SSOToken;
048: import com.iplanet.sso.SSOException;
049: import com.sun.portal.providers.context.ProviderContext;
050: import com.sun.portal.providers.context.ProviderContextException;
051: import com.sun.portal.providers.ProviderException;
052: import com.sun.portal.providers.Provider;
053: import com.sun.portal.providers.ProfileProviderAdapter;
054: import com.sun.portal.providers.ApplicationHelper;
055: import com.sun.portal.log.common.PortalLogger;
056:
057: /**
058: * Description of the Class
059: *
060: *@author byork
061: *@created March 21, 2003
062: */
063: public class LDAPABApplicationHelper extends ApplicationHelper
064: implements AddressBookApplicationHelper {
065:
066: /**
067: * Description of the Field
068: */
069: public AddressBookProvider provider = null;
070: protected String containerName = "";
071: public SSOAdapter ssoAdapter = null;
072: private MsgExpURL meUrl = null;
073: protected String appName = "";
074: protected ProviderContext provContext = null;
075: protected String charset = null;
076:
077: /**
078: * Description of the Field
079: */
080: public Properties adapterProperties = null;
081: private URL ldapABURL = null;
082:
083: private long checkInterval;
084: private long lastCheckTime = 0;
085:
086: private static String LDAP_DEFAULT_PORT = "389";
087: private static String IMAP_DEFAULT_PORT = "143";
088: private static String CLIENT_DEFAULT_PORT = "80";
089: private static String CLIENT_DEFAULT_PROTOCOL = "http";
090: private final static int JSP_URL = 0;
091: private final static int SUN_ONE_URL = 1;
092: private int urlType = -1;
093: private int configIndex = -1;
094:
095: // Create a logger for this class
096: private static Logger debugLogger = PortalLogger
097: .getLogger(LDAPABApplicationHelper.class);
098:
099: /**
100: * Initialize AddressBookApplicationHelper. Set adapterProperties
101: * with ssoAdapter properties
102: *
103: * @param provider AddressBookProvider
104: * @param ssoAdapter SSOAdapter
105: */
106: public void init(AddressBookProvider provider, SSOAdapter ssoAdapter)
107: throws Exception {
108: super .init((ProfileProviderAdapter) provider, ssoAdapter);
109: this .provider = provider;
110: this .ssoAdapter = ssoAdapter;
111: if (ssoAdapter != null) {
112: this .adapterProperties = ssoAdapter.getProperties();
113: }
114:
115: this .checkInterval = Integer.parseInt(adapterProperties
116: .getProperty("checkInterval", "5000"));
117: provContext = provider.getProviderContext();
118: SSOToken token = ssoAdapter.getSSOToken();
119: charset = token.getProperty("CharSet");
120: debugLogger.log(Level.FINER, "PSAC_CSPPA0027", charset);
121: }
122:
123: /**
124: * Returns a client URL, if supported by the service.
125: *
126: * @param provider AddressBookProvider
127: * @param ssoAdapter SSOAdapter
128: */
129: public String getStartURL(AddressBookProvider provider,
130: HttpServletRequest request) {
131: String url = null;
132:
133: try {
134: url = getApplicationURL(provider, request);
135: ProviderContext pc = provider.getProviderContext();
136: url = pc.escape(url);
137: } catch (Exception me) {
138: debugLogger.log(Level.FINE, "PSAC_CSPPA0063", me);
139: }
140:
141: return url;
142: }
143:
144: /**
145: * Returns client aware URL for ab application access to service associated
146: * with a particular instance of a LDAPABSSOAdapter.
147: *
148: *@return The applicationURL value
149: *@exception Exception
150: */
151: public String getApplicationURL(AddressBookProvider provider,
152: HttpServletRequest request) throws Exception {
153:
154: ProviderContext pc = provider.getProviderContext();
155: String clientURL = null;
156: String clientProtocol = adapterProperties.getProperty(
157: "clientProtocol", "http");
158: String clientPort = adapterProperties.getProperty("clientPort",
159: adapterProperties.getProperty("port", "80"));
160: String host = adapterProperties.getProperty("host");
161: String baseURL = clientProtocol + "://" + host + ":"
162: + clientPort;
163:
164: // check for valid session, if not valid then return base url
165: SSOToken tok = ssoAdapter.getSSOToken();
166:
167: if (tok != null) {
168: // Check to see if SSO is enabled on the server. If so, do not use session id in
169: // any urls.
170: if (adapterProperties.getProperty("serverSSOEnabled", "")
171: .equals("true")) {
172: // In order to enable Calendar Express SSO, must access server root.
173: clientURL = baseURL;
174: } else {
175: String enableProxyAuth = adapterProperties
176: .getProperty("enableProxyAuth");
177: String uid = null;
178: String password = null;
179: String domain = adapterProperties.getProperty("domain");
180:
181: if ((enableProxyAuth != null)
182: && (enableProxyAuth.equals("true"))) {
183: uid = adapterProperties
184: .getProperty("proxyAdminUid");
185: password = adapterProperties
186: .getProperty("proxyAdminPassword");
187: } else {
188: uid = adapterProperties.getProperty("uid");
189: password = adapterProperties
190: .getProperty("password");
191: }
192:
193: if (uid != null)
194: debugLogger.log(Level.FINER, "PSAC_CSPPA0044", uid);
195: if (domain != null)
196: debugLogger.log(Level.FINER, "PSAC_CSPPA0045",
197: domain);
198: if (baseURL != null)
199: debugLogger.log(Level.FINER, "PSAC_CSPPA0046",
200: baseURL);
201:
202: clientURL = getWebmailURL(uid, password, domain,
203: baseURL);
204: }
205: } else {
206: clientURL = baseURL;
207: }
208:
209: return clientURL;
210: }
211:
212: /**
213: * Authenticate the user to Webmail / Messenger Express. If the return cookie
214: * contains 'sid' then the user is considered authenticated
215: *
216: *@param user String - user name
217: *@param pass String - user password
218: *@param baseUrl Description of the Parameter
219: *@return sso_uri String - single sign on URL to the messenger
220: * express
221: */
222: private String getWebmailURL(String user, String pass,
223: String domain, String baseUrl) {
224: if ((baseUrl != null) && (!baseUrl.equals(""))
225: && (baseUrl.charAt(baseUrl.length() - 1) == '/')) {
226: baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
227: }
228: MsgExpURL newMEUrl = new MsgExpURL(user, pass, baseUrl);
229: boolean urlValid = false;
230: // If the single sign on url is already populated, check if any of
231: // of the user configurations have changed, and check if the
232: // session has timed out .. if yes, try and connect again.If not
233: // return the single sign on url
234:
235: // Check against the mail ME url
236: if ((meUrl != null) && (meUrl.equals(newMEUrl))
237: && (isValidSession(meUrl))) {
238: urlValid = true;
239: newMEUrl = meUrl;
240: debugLogger.finer("PSAC_CSPPA0047");
241: }
242:
243: if (!urlValid) {
244: // Otherwise, build the single sign on URL
245:
246: // Build WMAP protocol's Login command
247: String urlstr = baseUrl + "/login.msc?user="
248: + ProviderEditUtility.encode(user, charset)
249: + "&password="
250: + ProviderEditUtility.encode(pass, charset);
251: String enableProxyAuth = adapterProperties
252: .getProperty("enableProxyAuth");
253:
254: if ((enableProxyAuth != null)
255: && (enableProxyAuth.equals("true"))) {
256: SSOToken tok = null;
257:
258: try {
259: tok = ssoAdapter.getSSOToken();
260: } catch (SSOAdapterException ssoae) {
261: tok = null;
262: }
263:
264: if (tok != null) {
265: AMStoreConnection amsc = null;
266: AMUser auser = null;
267: String puid = null;
268: String usrAttr = adapterProperties.getProperty(
269: "userAttribute", "uid");
270:
271: try {
272: amsc = new AMStoreConnection(tok);
273: auser = amsc.getUser(tok.getPrincipal()
274: .getName());
275: puid = auser.getStringAttribute(usrAttr);
276: } catch (SSOException ssoe) {
277: debugLogger.log(Level.INFO, "PSAC_CSPPA0048",
278: ssoe);
279: } catch (AMException ame) {
280: debugLogger.log(Level.INFO, "PSAC_CSPPA0048",
281: ame);
282: }
283:
284: if ((puid != null) && (puid.length() > 0)) {
285: if (domain != null) {
286: puid = puid + "@" + domain;
287: }
288: urlstr += "&proxyauth="
289: + ProviderEditUtility.encode(puid,
290: charset);
291: }
292: }
293: } else {
294: if ((domain != null) && (!domain.equals(""))) {
295: String fqUser = user + "@" + domain;
296: urlstr = baseUrl
297: + "/login.msc?user="
298: + ProviderEditUtility.encode(fqUser,
299: charset) + "&password="
300: + ProviderEditUtility.encode(pass, charset);
301: } else {
302: urlstr = baseUrl + "/login.msc?user="
303: + ProviderEditUtility.encode(user, charset)
304: + "&password="
305: + ProviderEditUtility.encode(pass, charset);
306: debugLogger.finer("PSAC_CSPPA0049");
307: }
308: }
309:
310: String authUrl = getRelativeSsoUrl(urlstr, newMEUrl);
311: debugLogger.log(Level.FINER, "PSAC_CSPPA0050", authUrl);
312: if (authUrl != null) {
313: newMEUrl.setSsoUri(baseUrl + authUrl + "&view=portal");
314: } else {
315: newMEUrl = null;
316: debugLogger.finer("PSAC_CSPPA0051");
317: return null;
318: }
319: }
320: meUrl = newMEUrl;
321: String mailSessId = null;
322: if (newMEUrl != null) {
323: mailSessId = newMEUrl.getWebmailSessionId();
324: debugLogger.log(Level.FINER, "PSAC_CSPPA0052", mailSessId);
325: }
326: if (mailSessId == null) {
327: mailSessId = "";
328: }
329: if (newMEUrl != null) {
330: String test = newMEUrl.getSsoUri();
331: debugLogger.log(Level.FINER, "PSAC_CSPPA0053", test);
332: return newMEUrl.getSsoUri();
333: } else {
334: return baseUrl;
335: }
336: }
337:
338: /**
339: * Given the login URL with the user name and password filled in, this
340: * method returns a single sign on url with a valid session ID. To
341: * generate such a URL, an WMAP login command is sent to the Messenger
342: * Express and if the response contains a cookie with a 'sid' parameter,
343: * then the URL is generated.
344: *
345: * @param urlstr WMAP Login command Url with user name and password
346: * @param urlstr WMAP Login command Url with user name and password
347: *
348: * @return String Single Sign On URL
349: **/
350: private String getRelativeSsoUrl(String urlstr, MsgExpURL meURL) {
351: String authUrl = null;
352: HttpURLConnection urlconn = null;
353: try {
354: URL url = new URL(urlstr);
355: urlconn = (HttpURLConnection) url.openConnection();
356: urlconn.setInstanceFollowRedirects(false);
357:
358: } catch (MalformedURLException mfe) {
359: debugLogger.log(Level.INFO, "PSAC_CSPPA0054", meURL
360: .getBaseUri());
361: return null;
362: } catch (IOException ioe) {
363: debugLogger.log(Level.INFO, "PSAC_CSPPA0055", ioe);
364: return null;
365: }
366: String key;
367:
368: // Check if the headers of the response contain a Location field with
369: // parameter 'sid' set.
370: String location = urlconn.getHeaderField("Location");
371:
372: int sessionIdBegin = 0;
373: if ((sessionIdBegin = location.indexOf("sid")) < 0) {
374: // cannot authenticate to the Messenger Express
375: debugLogger.finer("PSAC_CSPPA0056");
376: meURL.setWebmailSessionId(null);
377: authUrl = null;
378: } else {
379: String inter = location.substring(sessionIdBegin + 4);
380: int sessionIdEnd = inter.indexOf("&");
381: String mailSessionId = inter.substring(0, sessionIdEnd);
382: meURL.setWebmailSessionId(mailSessionId);
383: if (location.charAt(0) != '/') {
384: authUrl = "/" + location;
385: } else {
386: authUrl = location;
387: }
388: }
389: return authUrl;
390: }
391:
392: /**
393: * Checks whether the current this.webmailSessionId for Messenger
394: * Express has timed out. This is done by checking if the page
395: * returned by sending a Get Mail WMAP command to messenger express
396: * contains string "parent.timeoutCB()". If yes, then the
397: * webmailSessionId has timed out.
398: *
399: * @return boolean
400: **/
401: private boolean isValidSession(MsgExpURL meURL) {
402:
403: Date newCheckDate = new Date();
404: long newCheckTime = newCheckDate.getTime();
405: long timeSinceLastCheck = newCheckTime - lastCheckTime;
406:
407: if (timeSinceLastCheck < checkInterval) {
408: return true;
409: }
410:
411: lastCheckTime = newCheckTime;
412:
413: String webmailSessionId = meURL.getWebmailSessionId();
414: if (webmailSessionId == null) {
415: debugLogger.finer("PSAC_CSPPA0057");
416: return false;
417: }
418: String pageContent = "";
419:
420: // Build the WMAP protocol's Get Mail command
421: // Get 0 messages (count=0) to reduce the traffic
422: String urlstr = meURL.baseUri
423: + "/mbox.msc?sid="
424: + webmailSessionId
425: + "&security=false&mbox=INBOX&start=0&count=20&date=false";
426:
427: HttpURLConnection urlconn = null;
428: try {
429: URL url = new URL(urlstr);
430: urlconn = (HttpURLConnection) url.openConnection();
431: urlconn.setInstanceFollowRedirects(false);
432: } catch (IOException ioe) {
433: debugLogger.log(Level.INFO, "PSAC_CSPPA0058", ioe);
434: pageContent = null;
435: meURL.setWebmailSessionId(null);
436: return false;
437: }
438: try {
439: BufferedReader in = new BufferedReader(
440: new InputStreamReader(urlconn.getInputStream()));
441: String inputLine = null;
442:
443: // Getting the content of the page
444: while ((inputLine = in.readLine()) != null) {
445: pageContent += inputLine;
446: }
447: in.close();
448: } catch (Exception e) {
449: debugLogger.log(Level.INFO, "PSAC_CSPPA0059", e);
450: e.printStackTrace();
451: pageContent = null;
452: meURL.setWebmailSessionId(null);
453: return false;
454: }
455: // Check if the page contents contain string "parent.timeoutCB()"
456: // If yes, then the webmailSessionId has timed out
457: if ((pageContent.indexOf("parent.timeoutCB()")) > 0) {
458: debugLogger.finer("PSAC_CSPPA0060");
459: pageContent = null;
460: meURL.setWebmailSessionId(null);
461: return false;
462: }
463: return true;
464: }
465:
466: /**
467: * Returns the contents of the MailProviders edit page
468: *
469: *@param aprov Description of the Parameter
470: *@param req Description of the Parameter
471: *@param res Description of the Parameter
472: *@return The appPrefsEdit value
473: */
474: public StringBuffer getAppPrefsEdit(AddressBookProvider aprov,
475: HttpServletRequest req, HttpServletResponse res) {
476: setEditContainer(aprov.editContainer);
477: setContainerName(aprov.containerName);
478: setTargetProvider(aprov.targetProvider);
479: return super .getAppPrefsEdit((Provider) aprov, req, res);
480: }
481:
482: /**
483: * Processes values returned from the MailPprovider edit page
484: *
485: *@param aprov Instance of Address Book Provider
486: *@param req servlet request
487: *@param res servlet response
488: */
489: public URL processAppPrefsEdit(AddressBookProvider aprov,
490: HttpServletRequest request, HttpServletResponse response)
491: throws ProviderException {
492: setEditContainer(aprov.editContainer);
493: setContainerName(aprov.containerName);
494: setTargetProvider(aprov.targetProvider);
495: return super .processAppPrefsEdit((Provider) aprov, request,
496: response);
497: }
498:
499: /**
500: * Implementation of abstract ApplicationHelper method
501: *
502: *@param req servlet request
503: *@return The String representing an URL to get to the edit page for DP
504: * properties
505: */
506:
507: public String getAppHelperEditLink(HttpServletRequest req,
508: ProviderContext pc) {
509: Hashtable tagTable = new Hashtable();
510: StringBuffer link = new StringBuffer();
511: try {
512: link.append(pc.getDesktopURL(req));
513: } catch (Exception e) {
514: return "";
515: }
516: link.append("?action=edit&provider=" + provider.editContainer);
517: link.append("&targetprovider=" + provider.targetProvider);
518: link.append("&containerName=" + provider.containerName);
519: link.append("&appPref=" + this .getName());
520: debugLogger.log(Level.INFO, "PSAC_CSPPA0061", link.toString());
521: tagTable.put("editLink", link.toString());
522: String content = null;
523:
524: try {
525: String fontTag = pc.getStringProperty(provider.getName(),
526: "fontFace1", "Sans-serif");
527: tagTable.put("iwtDesktop-fontFace1", fontTag);
528: content = pc.getTemplate(provider.getName(),
529: "edit-link.template", tagTable).toString();
530: debugLogger.log(Level.FINER, "PSAC_CSPPA0041", content
531: .toString());
532: } catch (Exception e) {
533: debugLogger.log(Level.INFO, "PSAC_CSPPA0042", e);
534: content = "";
535: }
536:
537: debugLogger.log(Level.FINER, "PSAC_CSPPA0043", content
538: .toString());
539:
540: return content;
541: }
542:
543: /**
544: * messenger Express URL inner class
545: *
546: */
547: private class MsgExpURL {
548: private String user = null;
549: private String pass = null;
550: private String baseUri = null;
551: // Result
552: private String webmailSessionId = null;
553: private String sso_uri = null;
554:
555: /*
556: * Constructor
557: */
558: /**
559: * Constructor for the MsgExpURL object
560: *
561: *@param user Username
562: *@param pass Password
563: *@param baseUri Base URI
564: */
565: MsgExpURL(String user, String pass, String baseUri) {
566: this .user = user;
567: this .pass = pass;
568: this .baseUri = baseUri;
569: }
570:
571: /**
572: * Tests equality of another MsgExpURL class to this class
573: *
574: *@param meUrl2Comp MsgExpURL class
575: *@return true if objects equal
576: */
577: boolean equals(MsgExpURL meUrl2Comp) {
578: // If any of the given arguments do not match the stored values,
579: // return false.
580: if ((!meUrl2Comp.baseUri.equals(this .baseUri))
581: || (!meUrl2Comp.user.equals(this .user))
582: || (!meUrl2Comp.pass.equals(this .pass))) {
583: return false;
584: }
585: return true;
586: }
587:
588: /**
589: * Gets the baseUri attribute of the MsgExpURL object
590: *
591: *@return The baseUri value
592: */
593: String getBaseUri() {
594: return this .baseUri;
595: }
596:
597: /**
598: * Gets the ssoUri attribute of the MsgExpURL object
599: *
600: *@return The ssoUri value
601: */
602: String getSsoUri() {
603: return this .sso_uri;
604: }
605:
606: /**
607: * Sets the ssoUri attribute of the MsgExpURL object
608: *
609: *@param sso_uri The new ssoUri value
610: */
611: void setSsoUri(String sso_uri) {
612: this .sso_uri = sso_uri;
613: }
614:
615: /**
616: * Gets the webmailSessionId attribute of the MsgExpURL object
617: *
618: *@return The webmailSessionId value
619: */
620: String getWebmailSessionId() {
621: return this .webmailSessionId;
622: }
623:
624: /**
625: * Sets the webmailSessionId attribute of the MsgExpURL object
626: *
627: *@param webmailSessionId The new webmailSessionId value
628: */
629: void setWebmailSessionId(String webmailSessionId) {
630: this .webmailSessionId = webmailSessionId;
631: }
632:
633: /**
634: * Clears out the instance variables for the class
635: */
636: void release() {
637: user = null;
638: pass = null;
639: baseUri = null;
640: sso_uri = null;
641: webmailSessionId = null;
642: }
643:
644: }
645: }
|