/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.security.jauth;
import java.util.*;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.AppConfigurationEntry;
import sun.security.util.Debug;
/**
* Shared logic from Client and ServerAuthContext reside here.
*/
final class AuthContext {
static final String INIT = "initialize";
static final String DISPOSE_SUBJECT = "disposeSubject";
static final String SECURE_REQUEST = "secureRequest";
static final String VALIDATE_RESPONSE = "validateResponse";
static final String VALIDATE_REQUEST = "validateRequest";
static final String SECURE_RESPONSE = "secureResponse";
// managesSessions method is implemented by looking for
// corresponding option value in module configuration
static final String MANAGES_SESSIONS = "managesSessions";
static final String MANAGES_SESSIONS_OPTION = "managessessions";
private ConfigFile.Entry[] entries;
private Debug debug;
AuthContext(ConfigFile.Entry[] entries,
Debug debug) throws AuthException {
this.entries = entries;
this.debug = debug;
}
/**
* Invoke modules according to configuration
*/
Object[] invoke(final String methodName, final Object[] args)
throws AuthException {
// invoke modules in a doPrivileged
final Object rValues[] = new Object[entries.length];
try {
java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction() {
public Object run() throws AuthException {
invokePriv(methodName, args, rValues);
return null;
}
});
} catch (java.security.PrivilegedActionException pae) {
if (pae.getException() instanceof AuthException) {
throw (AuthException)pae.getException();
} else {
AuthException ae = new AuthException();
ae.initCause(pae.getException());
throw ae;
}
}
return rValues;
}
void invokePriv(String methodName, Object[] args, Object[] rValues)
throws AuthException {
// special treatment for managesSessions until the module
// interface can be extended.
if (methodName.equals(AuthContext.MANAGES_SESSIONS)) {
for (int i = 0; i < entries.length; i++) {
Map options = entries[i].getOptions();
String mS = (String) options.get(AuthContext.MANAGES_SESSIONS_OPTION);
rValues[i] = Boolean.valueOf(mS);
}
return;
}
boolean success = false;
AuthException firstRequiredError = null;
AuthException firstError = null;
// XXX no way to reverse module invocation
for (int i = 0; i < entries.length; i++) {
// get initialized module instance
Object module = entries[i].module;
// invoke the module
try {
Method[] mArray = module.getClass().getMethods();
for (int j = 0; j < mArray.length; j++) {
if (mArray[j].getName().equals(methodName)) {
// invoke module
rValues[i] = mArray[j].invoke(module, args);
// success -
// return if SUFFICIENT and no previous REQUIRED errors
if (firstRequiredError == null &&
entries[i].getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT) {
if (debug != null) {
debug.println(entries[i].getLoginModuleName() +
"." +
methodName +
" SUFFICIENT success");
}
return;
}
if (debug != null) {
debug.println(entries[i].getLoginModuleName() +
"." +
methodName +
" success");
}
success = true;
break;
}
}
if (!success) {
// PLEASE NOTE:
// this exception will be thrown if any module
// in the context does not support the method.
NoSuchMethodException nsme =
new NoSuchMethodException("module " +
module.getClass().getName() +
" does not implement " +
methodName);
AuthException ae = new AuthException();
ae.initCause(nsme);
throw ae;
}
} catch (IllegalAccessException iae) {
AuthException ae = new AuthException();
ae.initCause(iae);
throw ae;
} catch (InvocationTargetException ite) {
// failure cases
AuthException ae;
if (ite.getCause() instanceof AuthException) {
ae = (AuthException)ite.getCause();
} else {
ae = new AuthException();
ae.initCause(ite.getCause());
}
if (entries[i].getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) {
if (debug != null) {
debug.println(entries[i].getLoginModuleName() +
"." +
methodName +
" REQUISITE failure");
}
// immediately throw exception
if (firstRequiredError != null) {
throw firstRequiredError;
} else {
throw ae;
}
} else if (entries[i].getControlFlag() ==
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) {
if (debug != null) {
debug.println(entries[i].getLoginModuleName() +
"." +
methodName +
" REQUIRED failure");
}
// save exception and continue
if (firstRequiredError == null) {
firstRequiredError = ae;
}
} else {
if (debug != null) {
debug.println(entries[i].getLoginModuleName() +
"." +
methodName +
" OPTIONAL failure");
}
// save exception and continue
if (firstError == null) {
firstError = ae;
}
}
}
}
// done invoking entire stack of modules
if (firstRequiredError != null) {
throw firstRequiredError;
} else if (firstError != null && !success) {
throw firstError;
}
// if no errors, return gracefully
if (debug != null) {
debug.println("overall " + methodName + " success");
}
}
}
|