/** * Begin user authentication. * * <p>Acquire the user's credentials and verify them against the specified LDAP directory. * * @return true always, since this <code>LoginModule</code> should not be ignored. * @exception FailedLoginException if the authentication fails. * @exception LoginException if this <code>LoginModule</code> is unable to perform the * authentication. */ public boolean login() throws LoginException { if (userProvider == null) { throw new LoginException("Unable to locate the LDAP directory service"); } if (debug) { System.out.println("\t\t[LdapLoginModule] user provider: " + userProvider); } // attempt the authentication if (tryFirstPass) { try { // attempt the authentication by getting the // username and password from shared state attemptAuthentication(true); // authentication succeeded succeeded = true; if (debug) { System.out.println("\t\t[LdapLoginModule] " + "tryFirstPass succeeded"); } return true; } catch (LoginException le) { // authentication failed -- try again below by prompting cleanState(); if (debug) { System.out.println("\t\t[LdapLoginModule] " + "tryFirstPass failed: " + le.toString()); } } } else if (useFirstPass) { try { // attempt the authentication by getting the // username and password from shared state attemptAuthentication(true); // authentication succeeded succeeded = true; if (debug) { System.out.println("\t\t[LdapLoginModule] " + "useFirstPass succeeded"); } return true; } catch (LoginException le) { // authentication failed cleanState(); if (debug) { System.out.println("\t\t[LdapLoginModule] " + "useFirstPass failed"); } throw le; } } // attempt the authentication by prompting for the username and pwd try { attemptAuthentication(false); // authentication succeeded succeeded = true; if (debug) { System.out.println("\t\t[LdapLoginModule] " + "authentication succeeded"); } return true; } catch (LoginException le) { cleanState(); if (debug) { System.out.println("\t\t[LdapLoginModule] " + "authentication failed"); } throw le; } }
private void invoke(String methodName) throws LoginException { // start at moduleIndex // - this can only be non-zero if methodName is LOGIN_METHOD for (int i = moduleIndex; i < moduleStack.length; i++, moduleIndex++) { try { int mIndex = 0; Method[] methods = null; if (moduleStack[i].module != null) { methods = moduleStack[i].module.getClass().getMethods(); } else { // instantiate the LoginModule // // Allow any object to be a LoginModule as long as it // conforms to the interface. Class<?> c = Class.forName(moduleStack[i].entry.getLoginModuleName(), true, contextClassLoader); Constructor<?> constructor = c.getConstructor(PARAMS); Object[] args = {}; moduleStack[i].module = constructor.newInstance(args); // call the LoginModule's initialize method methods = moduleStack[i].module.getClass().getMethods(); for (mIndex = 0; mIndex < methods.length; mIndex++) { if (methods[mIndex].getName().equals(INIT_METHOD)) { break; } } Object[] initArgs = {subject, callbackHandler, state, moduleStack[i].entry.getOptions()}; // invoke the LoginModule initialize method // // Throws ArrayIndexOutOfBoundsException if no such // method defined. May improve to use LoginException in // the future. methods[mIndex].invoke(moduleStack[i].module, initArgs); } // find the requested method in the LoginModule for (mIndex = 0; mIndex < methods.length; mIndex++) { if (methods[mIndex].getName().equals(methodName)) { break; } } // set up the arguments to be passed to the LoginModule method Object[] args = {}; // invoke the LoginModule method // // Throws ArrayIndexOutOfBoundsException if no such // method defined. May improve to use LoginException in // the future. boolean status = ((Boolean) methods[mIndex].invoke(moduleStack[i].module, args)).booleanValue(); if (status == true) { // if SUFFICIENT, return if no prior REQUIRED errors if (!methodName.equals(ABORT_METHOD) && !methodName.equals(LOGOUT_METHOD) && moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT && firstRequiredError == null) { // clear state clearState(); if (debug != null) debug.println(methodName + " SUFFICIENT success"); return; } if (debug != null) debug.println(methodName + " success"); success = true; } else { if (debug != null) debug.println(methodName + " ignored"); } } catch (NoSuchMethodException nsme) { MessageFormat form = new MessageFormat( ResourcesMgr.getString( "unable.to.instantiate.LoginModule.module.because.it.does.not.provide.a.no.argument.constructor")); Object[] source = {moduleStack[i].entry.getLoginModuleName()}; throwException(null, new LoginException(form.format(source))); } catch (InstantiationException ie) { throwException( null, new LoginException( ResourcesMgr.getString("unable.to.instantiate.LoginModule.") + ie.getMessage())); } catch (ClassNotFoundException cnfe) { throwException( null, new LoginException( ResourcesMgr.getString("unable.to.find.LoginModule.class.") + cnfe.getMessage())); } catch (IllegalAccessException iae) { throwException( null, new LoginException( ResourcesMgr.getString("unable.to.access.LoginModule.") + iae.getMessage())); } catch (InvocationTargetException ite) { // failure cases LoginException le; if (ite.getCause() instanceof PendingException && methodName.equals(LOGIN_METHOD)) { // XXX // // if a module's LOGIN_METHOD threw a PendingException // then immediately throw it. // // when LoginContext is called again, // the module that threw the exception is invoked first // (the module list is not invoked from the start). // previously thrown exception state is still present. // // it is assumed that the module which threw // the exception can have its // LOGIN_METHOD invoked twice in a row // without any commit/abort in between. // // in all cases when LoginContext returns // (either via natural return or by throwing an exception) // we need to call clearState before returning. // the only time that is not true is in this case - // do not call throwException here. throw (PendingException) ite.getCause(); } else if (ite.getCause() instanceof LoginException) { le = (LoginException) ite.getCause(); } else if (ite.getCause() instanceof SecurityException) { // do not want privacy leak // (e.g., sensitive file path in exception msg) le = new LoginException("Security Exception"); le.initCause(new SecurityException()); if (debug != null) { debug.println( "original security exception with detail msg " + "replaced by new exception with empty detail msg"); debug.println("original security exception: " + ite.getCause().toString()); } } else { // capture an unexpected LoginModule exception java.io.StringWriter sw = new java.io.StringWriter(); ite.getCause().printStackTrace(new java.io.PrintWriter(sw)); sw.flush(); le = new LoginException(sw.toString()); } if (moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) { if (debug != null) debug.println(methodName + " REQUISITE failure"); // if REQUISITE, then immediately throw an exception if (methodName.equals(ABORT_METHOD) || methodName.equals(LOGOUT_METHOD)) { if (firstRequiredError == null) firstRequiredError = le; } else { throwException(firstRequiredError, le); } } else if (moduleStack[i].entry.getControlFlag() == AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) { if (debug != null) debug.println(methodName + " REQUIRED failure"); // mark down that a REQUIRED module failed if (firstRequiredError == null) firstRequiredError = le; } else { if (debug != null) debug.println(methodName + " OPTIONAL failure"); // mark down that an OPTIONAL module failed if (firstError == null) firstError = le; } } } // we went thru all the LoginModules. if (firstRequiredError != null) { // a REQUIRED module failed -- return the error throwException(firstRequiredError, null); } else if (success == false && firstError != null) { // no module succeeded -- return the first error throwException(firstError, null); } else if (success == false) { // no module succeeded -- all modules were IGNORED throwException( new LoginException(ResourcesMgr.getString("Login.Failure.all.modules.ignored")), null); } else { // success clearState(); return; } }