001: /**
002: * $Id: MSISDN.java,v 1.2 2004/01/21 20:41:39 sathyakn Exp $
003: * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
004: *
005: * U.S. Government Rights - Commercial software. Government users
006: * are subject to the Sun Microsystems, Inc. standard license
007: * agreement and applicable provisions of the FAR and its
008: * supplements.
009: *
010: * Use is subject to license terms.
011: *
012: * This distribution may include materials developed by third
013: * parties.Sun, Sun Microsystems, the Sun logo and Java are
014: * trademarks or registered trademarks of Sun Microsystems, Inc.
015: * in the U.S. and other countries.
016: *
017: * Copyright © 2003 Sun Microsystems, Inc. Tous droits réservés.
018: *
019: * L'utilisation est soumise aux termes du contrat de licence.
020: *
021: * Cette distribution peut comprendre des composants développés
022: * par des tierces parties.
023: *
024: * Sun, Sun Microsystems, le logo Sun et Java sont des marques de
025: * fabrique ou des marques déposées de Sun Microsystems, Inc. aux
026: * Etats-Unis et dans d'autres pays.
027: */package com.sun.identity.authentication.modules.msisdn;
028:
029: import java.util.ResourceBundle;
030: import java.util.Set;
031: import java.util.Map;
032: import java.util.Iterator;
033: import java.util.HashMap;
034:
035: import javax.servlet.http.HttpServletRequest;
036: import javax.servlet.http.Cookie;
037:
038: import netscape.ldap.LDAPConnection;
039: import netscape.ldap.LDAPSearchResults;
040: import netscape.ldap.LDAPEntry;
041: import netscape.ldap.LDAPException;
042:
043: import com.sun.identity.authentication.spi.AMLoginModule;
044: import com.iplanet.am.util.Misc;
045: import com.iplanet.am.util.SSLSocketFactoryManager;
046:
047: import javax.security.auth.Subject;
048: import javax.security.auth.callback.CallbackHandler;
049: import javax.security.auth.callback.Callback;
050: import javax.security.auth.callback.NameCallback;
051: import javax.security.auth.callback.PasswordCallback;
052: import javax.security.auth.login.LoginException;
053:
054: public class MSISDN extends AMLoginModule {
055:
056: private ResourceBundle bundle = null;
057: private static com.iplanet.am.util.Debug debug = null;
058: private static final int DEFAULT_MSISDN_AUTH_LEVEL = 0;
059:
060: private String userTokenId;
061:
062: private String errorMsg = null;
063: private final int FINISHED = -1;
064:
065: private MSISDNAuthPrincipal userPrincipal;
066: private CallbackHandler callbackHandler;
067:
068: private Map options;
069:
070: private Set gatewayList;
071: private Set parameterNameList;
072: private int authLevel;
073: private String userSearchAttr;
074: private String serverHost;
075: private int serverPort = 389;
076: private String startSearchLoc;
077: private String principleUser;
078: private String principlePasswd;
079: private String useSSL;
080:
081: public MSISDN() throws LoginException {
082: }
083:
084: public void init(Subject subject, Map sharedState, Map options) {
085: if (debug == null) {
086: debug = com.iplanet.am.util.Debug
087: .getInstance("amAuthMSISDN");
088: }
089: java.util.Locale locale = getLoginLocale();
090: bundle = amCache.getResBundle("amAuthMSISDN", locale);
091: if (debug.messageEnabled()) {
092: debug.message("MSISDN resbundle locale=" + locale);
093: }
094:
095: this .options = options;
096: initAuthConfig();
097: }
098:
099: /**
100: * Gets MSISDN auth config parameters.
101: */
102: private void initAuthConfig() {
103: if (options != null) {
104: debug.message("MSISDN: getting attributes.");
105:
106: gatewayList = (Set) options
107: .get("iplanet-am-auth-msisdn-trusted-gateway-list");
108: parameterNameList = (Set) options
109: .get("iplanet-am-auth-msisdn-parameter-name-list");
110:
111: String tmp = Misc.getMapAttr(options,
112: "iplanet-am-auth-msisdn-auth-level");
113:
114: if (tmp == null || tmp.equals("")) {
115: authLevel = DEFAULT_MSISDN_AUTH_LEVEL;
116: } else {
117: try {
118: authLevel = Integer.parseInt(tmp);
119: } catch (Exception e) {
120: debug.error("Invalid auth level " + tmp);
121: authLevel = DEFAULT_MSISDN_AUTH_LEVEL;
122: }
123: }
124: userSearchAttr = Misc.getMapAttr(options,
125: "iplanet-am-auth-msisdn-user-search-attribute");
126: principleUser = Misc.getMapAttr(options,
127: "iplanet-am-auth-msisdn-principal-user");
128: principlePasswd = Misc.getMapAttr(options,
129: "iplanet-am-auth-msisdn-principal-passwd");
130: useSSL = Misc.getMapAttr(options,
131: "iplanet-am-auth-msisdn-use-ssl");
132: serverHost = Misc.getServerMapAttr(options,
133: "iplanet-am-auth-msisdn-ldap-provider-url");
134:
135: if (serverHost == null) {
136: debug
137: .error("Fatal error: LDAP Server and Port misconfigured");
138: errorMsg = bundle.getString("wrongLDAPServer");
139: return;
140: }
141:
142: String port = null;
143: if (serverHost != null) {
144: // set LDAP Parameters
145: int index = serverHost.indexOf(':');
146: if (index != -1) {
147: port = serverHost.substring(index + 1);
148: serverPort = Integer.parseInt(port);
149: serverHost = serverHost.substring(0, index);
150: }
151: }
152: startSearchLoc = Misc.getServerMapAttr(options,
153: "iplanet-am-auth-msisdn-base-dn");
154: if (startSearchLoc == null) {
155: debug
156: .error("Fatal error: LDAP Start Search DN misconfigured");
157: errorMsg = bundle.getString("wrongStartDN");
158: return;
159: }
160:
161: if (debug.messageEnabled()) {
162: debug.message("\n ldapProviderUrl=" + serverHost
163: + "\n\t serverPort (" + port + ") = "
164: + serverPort + "\n\t startSearchLoc="
165: + startSearchLoc + "\n\t userSearchAttr="
166: + userSearchAttr + "\n\t principleUser="
167: + principleUser + "\n\t authLevel=" + authLevel
168: + "\n\t useSSL=" + useSSL);
169: }
170: } else {
171: debug.error("options is null");
172: errorMsg = bundle.getString("MSISDNValidateEx");
173: }
174: }
175:
176: public int process(Callback[] callbacks, int state)
177: throws LoginException {
178: debug.message("MSISDN : in process ..");
179: if (errorMsg != null) {
180: throw new LoginException(errorMsg);
181: }
182:
183: HttpServletRequest req = getHttpServletRequest();
184: String gateway = null;
185: String msisdnNumber = null;
186:
187: if (req != null) {
188: gateway = req.getRemoteAddr();
189:
190: Iterator it = parameterNameList.iterator();
191: String parameterName = null;
192: String cookieName = null;
193: int index;
194: while (it.hasNext()) {
195: parameterName = it.next().toString();
196: if (debug.messageEnabled()) {
197: debug.message("parameterName : " + parameterName);
198: }
199:
200: // see if it's cookie
201: // Syntax :: "Cookie:cookie_name"
202: index = parameterName.indexOf(':');
203: if (index != -1) {
204: String cookieStr = parameterName
205: .substring(0, index);
206: if (cookieStr.equalsIgnoreCase("Cookie")) {
207: // parameter name is a cookie name.
208: cookieName = parameterName.substring(index + 1);
209: }
210: if (cookieName != null && cookieName.length() > 0) {
211: if (debug.messageEnabled()) {
212: debug.message("cookieName : " + cookieName);
213: }
214: Cookie cookieArray[] = req.getCookies();
215: for (int i = 0; i < cookieArray.length; i++) {
216: if (cookieArray[i].getName()
217: .equalsIgnoreCase(cookieName)) {
218: msisdnNumber = cookieArray[i]
219: .getValue();
220: break; // break from for loop
221: }
222: }// end for
223: // if MSISDN number is found in cookies come out
224: if (msisdnNumber != null) {
225: break; // break from while loop
226: }
227: }// end inner if
228: }// end outer if
229:
230: // check in headers.
231: msisdnNumber = req.getHeader(parameterName);
232: if (msisdnNumber != null) {
233: break;
234: }
235: // check in query/body
236: msisdnNumber = req.getParameter(parameterName);
237: if (msisdnNumber != null) {
238: break;
239: }
240: }//end while
241: } else {
242: debug.message("MSISDN : null request calling sendCallback");
243: Map map = sendCallback();
244: if (map == null) {
245: debug.error(" null map from sendCallback : ");
246: throw new LoginException(bundle
247: .getString("MSISDNValidateEx"));
248: }
249: gateway = (String) map.get("gateway");
250: msisdnNumber = (String) map.get("msisdnNumber");
251: }
252:
253: if (debug.messageEnabled()) {
254: debug.message("MSISDN : " + msisdnNumber + " gateway: "
255: + gateway);
256: }
257:
258: if (msisdnNumber == null || gateway == null) {
259: debug.error(" null value MSISDN : " + msisdnNumber
260: + " gateway: " + gateway);
261: throw new LoginException(bundle
262: .getString("MSISDNValidateEx"));
263: }
264:
265: userTokenId = getUserId(msisdnNumber);
266:
267: if (userTokenId != null) {
268: if (debug.messageEnabled()) {
269: debug.message("User Found : " + userTokenId);
270: }
271: boolean gatewayFound = false;
272:
273: Iterator it = gatewayList.iterator();
274: while (it.hasNext()) {
275: if (gateway.equalsIgnoreCase(it.next().toString())) {
276: gatewayFound = true;
277: break;
278: }
279: }
280: if (!gatewayFound) {
281: if (debug.messageEnabled()) {
282: debug.message("gateway not found : " + gateway);
283: }
284: setFailureID(userTokenId);
285: throw new LoginException(bundle
286: .getString("MSISDNValidateEx"));
287: }
288:
289: } else {
290: debug.error(" msisdnNumber not matched : " + msisdnNumber);
291: throw new LoginException(bundle
292: .getString("MSISDNValidateEx"));
293: }
294: return FINISHED;
295: }
296:
297: private String getUserId(String msisdnNumber) throws LoginException {
298: LDAPConnection ldc = null;
299: if (useSSL.equals("true")) {
300: debug.message("MSISDN: initial ldc using ssl.");
301: try {
302: ldc = new LDAPConnection(SSLSocketFactoryManager
303: .getSSLSocketFactory());
304: debug.message("validate(): SSLSocketFactory called");
305: } catch (Exception e) {
306: debug.error("validate.JSSSocketFactory", e);
307: throw new LoginException(bundle
308: .getString("jssSokFactoryFail"));
309: }
310: } else { // non-ssl
311: ldc = new LDAPConnection();
312: }
313:
314: try {
315: ldc.connect(serverHost, serverPort);
316: ldc.authenticate(3, principleUser, principlePasswd);
317: } catch (LDAPException e) {
318: debug.error("MSISDN : dircontext", e);
319: throw new LoginException(bundle
320: .getString("MSISDNNoContext"));
321:
322: }
323:
324: try {
325: if (debug.messageEnabled()) {
326: debug.message("MSISDN - ldc.search: searching "
327: + startSearchLoc + " " + ldc);
328: }
329: String searchFilter = new StringBuffer(250).append("(")
330: .append(userSearchAttr).append("=").append(
331: msisdnNumber).append(")").toString();
332:
333: if (debug.messageEnabled()) {
334: debug
335: .message("MSISDN - ldc.search: using this filter: "
336: + searchFilter);
337: }
338:
339: //
340: // we are interested only in dn & also saves memory (especially
341: // when the entry contains the display profile !)
342: //
343: String[] attrs = { "dn" };
344: LDAPSearchResults results = ldc.search(startSearchLoc,
345: LDAPConnection.SCOPE_SUB, searchFilter, attrs,
346: false);
347:
348: if (results != null && results.hasMoreElements()) {
349: if (results.getCount() > 1) {
350: debug.error("Multiple entries matched: "
351: + results.getCount());
352: throw new LoginException(bundle
353: .getString("MultipleUIDMatch"));
354: }
355: LDAPEntry entry = results.next();
356: String userDN = entry.getDN();
357:
358: if (debug.messageEnabled()) {
359: debug.message("MSISDN - userDN : " + userDN);
360: }
361: return userDN;
362: }
363: } catch (Exception e) {
364: debug.error("MSISDN - Error finding user: ", e);
365: throw new LoginException(bundle.getString("UserNotFound"));
366: }
367: if (debug.messageEnabled()) {
368: debug
369: .message("MSISDN - user not found with given MSISDN Number:"
370: + msisdnNumber);
371: }
372: return null;
373: }
374:
375: public java.security.Principal getPrincipal() {
376: if (userPrincipal != null) {
377: return userPrincipal;
378: } else if (userTokenId != null) {
379: userPrincipal = new MSISDNAuthPrincipal(userTokenId);
380: return userPrincipal;
381: } else {
382: return null;
383: }
384: }
385:
386: /**
387: * Send callbacks to get gateway and/or msisdnNumber
388: * @return Map contains gateway and/or msisdnNumber
389: */
390: private Map sendCallback() {
391: try {
392: CallbackHandler callbackHandler = getCallbackHandler();
393: if (callbackHandler == null) {
394: throw new LoginException(bundle
395: .getString("NoCallbackHandler"));
396: }
397: Callback[] callbacks = new Callback[2];
398: callbacks[0] = new NameCallback(bundle.getString("gateway"));
399: callbacks[1] = new PasswordCallback(bundle
400: .getString("msisdn"), true);
401: if (debug.messageEnabled()) {
402: debug.message("Callback is.. :" + callbacks);
403: }
404: callbackHandler.handle(callbacks);
405:
406: // map to hold return
407: Map map = new HashMap();
408:
409: // process return
410: int len = callbacks.length;
411: for (int i = 0; i < len; i++) {
412: Callback cb = callbacks[i];
413: if (cb instanceof PasswordCallback) {
414: char[] pass = ((PasswordCallback) cb).getPassword();
415: if (pass != null) {
416: map.put("msisdnNumber", new String(pass));
417: }
418: } else if (cb instanceof NameCallback) {
419: String gateway = ((NameCallback) cb).getName();
420: if (gateway != null) {
421: map.put("gateway", gateway);
422: }
423: }
424: }
425: return map;
426: } catch (Exception e) {
427: debug.error("sendCallback", e);
428: }
429: return null;
430: }
431: }
|