[jboss-cvs] JBossAS SVN: r63068 - in trunk: security and 21 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue May 15 23:26:51 EDT 2007


Author: anil.saldhana at jboss.com
Date: 2007-05-15 23:26:51 -0400 (Tue, 15 May 2007)
New Revision: 63068

Added:
   trunk/security/
   trunk/security/.classpath
   trunk/security/.project
   trunk/security/build.xml
   trunk/security/src/
   trunk/security/src/etc/
   trunk/security/src/etc/default.mf
   trunk/security/src/main/
   trunk/security/src/main/org/
   trunk/security/src/main/org/jboss/
   trunk/security/src/main/org/jboss/crypto/
   trunk/security/src/main/org/jboss/crypto/CipherClientSocketFactory.java
   trunk/security/src/main/org/jboss/crypto/CipherServerSocket.java
   trunk/security/src/main/org/jboss/crypto/CipherServerSocketFactory.java
   trunk/security/src/main/org/jboss/crypto/CipherSocket.java
   trunk/security/src/main/org/jboss/crypto/digest/
   trunk/security/src/main/org/jboss/crypto/digest/DigestCallback.java
   trunk/security/src/main/org/jboss/crypto/digest/SHAInterleave.java
   trunk/security/src/main/org/jboss/crypto/digest/SHAReverseInterleave.java
   trunk/security/src/main/org/jboss/security/
   trunk/security/src/main/org/jboss/security/AbstractSecurityProxy.java
   trunk/security/src/main/org/jboss/security/AuthorizationManagerFactory.java
   trunk/security/src/main/org/jboss/security/SecurityActions.java
   trunk/security/src/main/org/jboss/security/SubjectSecurityProxy.java
   trunk/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java
   trunk/security/src/main/org/jboss/security/auth/
   trunk/security/src/main/org/jboss/security/auth/SystemAuthenticator.java
   trunk/security/src/main/org/jboss/security/auth/SystemAuthenticatorMBean.java
   trunk/security/src/main/org/jboss/security/auth/login/
   trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfig.java
   trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfigMBean.java
   trunk/security/src/main/org/jboss/security/auth/login/SunConfigParser.jj
   trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfig.java
   trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigImpl.java
   trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigMBean.java
   trunk/security/src/main/org/jboss/security/auth/spi/
   trunk/security/src/main/org/jboss/security/auth/spi/RFC2617Digest.java
   trunk/security/src/main/org/jboss/security/jce/
   trunk/security/src/main/org/jboss/security/jce/JCEProviderService.java
   trunk/security/src/main/org/jboss/security/jce/JCEProviderServiceMBean.java
   trunk/security/src/main/org/jboss/security/jndi/
   trunk/security/src/main/org/jboss/security/jndi/JndiLoginInitialContextFactory.java
   trunk/security/src/main/org/jboss/security/jndi/LoginInitialContextFactory.java
   trunk/security/src/main/org/jboss/security/jndi/SecurityAssociationActions.java
   trunk/security/src/main/org/jboss/security/package.html
   trunk/security/src/main/org/jboss/security/plugins/
   trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerService.java
   trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerServiceMBean.java
   trunk/security/src/main/org/jboss/security/plugins/DefaultLoginConfig.java
   trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomain.java
   trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomainMBean.java
   trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManager.java
   trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java
   trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java
   trunk/security/src/main/org/jboss/security/plugins/SecurityConfig.java
   trunk/security/src/main/org/jboss/security/plugins/SecurityConfigMBean.java
   trunk/security/src/main/org/jboss/security/plugins/SecurityDomainContext.java
   trunk/security/src/main/org/jboss/security/plugins/SecurityManagerMBean.java
   trunk/security/src/main/org/jboss/security/plugins/package.html
   trunk/security/src/main/org/jboss/security/propertyeditor/
   trunk/security/src/main/org/jboss/security/propertyeditor/PrincipalEditor.java
   trunk/security/src/main/org/jboss/security/propertyeditor/SecurityDomainEditor.java
   trunk/security/src/main/org/jboss/security/ssl/
   trunk/security/src/main/org/jboss/security/ssl/ClientSocketFactory.java
   trunk/security/src/main/org/jboss/security/ssl/Context.java
   trunk/security/src/main/org/jboss/security/ssl/DomainServerSocket.java
   trunk/security/src/main/org/jboss/security/ssl/DomainServerSocketFactory.java
   trunk/security/src/main/org/jboss/security/ssl/DomainSocketFactory.java
   trunk/security/src/main/org/jboss/security/ssl/RMISSLClientSocketFactory.java
   trunk/security/src/main/org/jboss/security/ssl/RMISSLServerSocketFactory.java
   trunk/security/src/tests/
   trunk/security/src/tests/org/
   trunk/security/src/tests/org/jboss/
   trunk/security/src/tests/org/jboss/test/
   trunk/security/src/tests/org/jboss/test/LoginContextTestCase.java
   trunk/security/src/tests/org/jboss/test/SunConfigParserTestCase.java
   trunk/security/src/tests/org/jboss/test/ldap/
   trunk/security/src/tests/org/jboss/test/ldap/LoginModulesTestCase.java
Log:
SECURITY-26: JBoss5 integration code

Added: trunk/security/.classpath
===================================================================
--- trunk/security/.classpath	                        (rev 0)
+++ trunk/security/.classpath	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/main"/>
+	<classpathentry kind="src" path="src/tests"/>
+	<classpathentry kind="lib" path="output/lib/jbosssx-server.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/security/lib/jbosssx.jar" sourcepath="/thirdparty/jboss/security/lib/jbosssx-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/security/lib/jbosssx-client.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/security-spi/lib/jboss-security-spi.jar" sourcepath="/thirdparty/jboss/security-spi/lib/jboss-security-spi-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-logging-spi/lib/jboss-logging-spi.jar" sourcepath="/thirdparty/jboss/common-logging-spi/lib/jboss-logging-spi-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-logging-spi/lib/jboss-logging-spi-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/javassist/lib/javassist.jar" sourcepath="/thirdparty/javassist/lib/javassist-src.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/javassist/lib/javassist-src.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/naming"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/system"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/system-jmx"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/j2se"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/jbossxb/lib/jboss-xml-binding.jar" sourcepath="/thirdparty/jboss/jbossxb/lib/jboss-xml-binding-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-microcontainer.jar" sourcepath="/thirdparty/jboss/microcontainer/lib/jboss-microcontainer-src.zip"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-deployers.jar" sourcepath="/home/tdiesler/svn/jbossmc/trunk/deployers/src/main"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-deployers-src.zip"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-microcontainer-src.zip"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-core/lib/jboss-common-core.jar" sourcepath="/thirdparty/jboss/common-core/lib/jboss-common-core-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-core/lib/jboss-common-core-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/junit/lib/junit.jar" sourcepath="/thirdparty/junit/lib/junit-src.zip"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/jboss-javaee/lib/jboss-javaee.jar" sourcepath="/thirdparty/jboss/jboss-javaee/lib/jboss-javaee-sources.jar"/>
+	<classpathentry kind="output" path="output/eclipse-classes"/>
+</classpath>

Added: trunk/security/.project
===================================================================
--- trunk/security/.project	                        (rev 0)
+++ trunk/security/.project	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>security</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: trunk/security/build.xml
===================================================================
--- trunk/security/build.xml	                        (rev 0)
+++ trunk/security/build.xml	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE project [
+   <!ENTITY buildmagic SYSTEM "../tools/etc/buildmagic/buildmagic.ent">
+   <!ENTITY modules SYSTEM "../tools/etc/buildmagic/modules.ent">
+   <!ENTITY libraries SYSTEM "../thirdparty/libraries.ent">
+]>
+
+<!-- ====================================================================== -->
+<!--                                                                        -->
+<!--  JBoss, the OpenSource J2EE webOS                                      -->
+<!--                                                                        -->
+<!--  Distributable under LGPL license.                                     -->
+<!--  See terms of license at http://www.gnu.org.                           -->
+<!--                                                                        -->
+<!-- ====================================================================== -->
+
+<!-- $Id: build.xml 57108 2006-09-23 20:55:54Z scott.stark at jboss.org $ -->
+
+<project default="main" name="JBoss/Security">
+
+  <!-- ================================================================== -->
+  <!-- Setup                                                              -->
+  <!-- ================================================================== -->
+
+  <!--
+     | Include the common Buildmagic elements.
+     |
+     | This defines several different targets, properties and paths.
+     | It also sets up the basic extention tasks amoung other things.
+   -->
+
+  &buildmagic;
+
+
+  <!-- ================================================================== -->
+  <!-- Initialization                                                     -->
+  <!-- ================================================================== -->
+
+  <!--
+     | Initialize the build system.  Must depend on '_buildmagic:init'.  
+     | Other targets should depend on 'init' or things will mysteriously fail.
+   -->
+
+  <target name="init" unless="init.disable" depends="_buildmagic:init">
+  </target>
+
+
+  <!-- ================================================================== -->
+  <!-- Configuration                                                      -->
+  <!-- ================================================================== -->
+
+  <!--
+     | Configure the build system.  
+     |
+     | This target is invoked by the Buildmagic initialization logic and 
+     | should contain module specific configuration elements.
+   -->
+
+  <target name="configure" unless="configure.disable">
+
+    <!-- =================== -->
+    <!-- Basic Configuration -->
+    <!-- =================== -->
+
+    <!-- Module name(s) & version -->
+    <property name="module.name" value="security"/>
+    <property name="module.Name" value="JBoss Security"/>
+
+    <!-- ========= -->
+    <!-- Libraries -->
+    <!-- ========= -->
+    &libraries;
+    
+    <path id="library.classpath">
+       <path refid="apache.log4j.classpath"/>
+       <path refid="javassist.classpath"/>
+    </path>
+
+   
+
+    <!-- ======= -->
+    <!-- Modules -->
+    <!-- ======= -->
+
+    &modules;
+
+    <!-- The combined dependent module classpath -->
+    <path id="dependentmodule.classpath">
+      <path refid="jboss.common.core.classpath"/>
+      <path refid="jboss.common.logging.spi.classpath"/>
+      <path refid="jboss.common.logging.log4j.classpath"/>
+      <path refid="jboss.common.logging.jdk.classpath"/>
+      <path refid="jboss.j2se.classpath"/>
+      <path refid="jboss.j2ee.classpath"/>
+      <path refid="jboss.jbossxb.classpath"/>
+      <path refid="jboss.microcontainer.classpath"/>
+      <path refid="jboss.naming.classpath"/>
+      <path refid="jboss.security.spi.classpath"/>
+      <path refid="jboss.security.classpath"/>
+      <path refid="jboss.system.classpath"/>
+      <path refid="jboss.systemjmx.classpath"/>
+    </path>
+
+    <!-- ===== -->
+    <!-- Tasks -->
+    <!-- ===== -->
+
+    <!-- Where source files live -->
+    <property name="source.java" value="${module.source}/main"/>
+    <property name="source.etc" value="${module.source}/etc"/>
+
+    <!-- Where build generated files will go -->
+    <property name="build.reports" value="${module.output}/reports"/>
+    <property name="build.classes" value="${module.output}/classes"/>
+    <property name="build.lib" value="${module.output}/lib"/>
+    <property name="build.api" value="${module.output}/api"/>
+    <property name="build.etc" value="${module.output}/etc"/>
+    <property name="build.gen-src" value="${module.output}/gen-src"/>
+
+    <!-- Install/Release structure -->
+    <property name="install.id" value="${module.name}-${module.version}"/>
+    <property name="release.id" value="${install.id}"/>
+    <property name="install.root" value="${module.output}/${install.id}"/>
+
+    <!-- The combined thirdparty classpath -->
+    <path id="thirdparty.classpath">
+      <path refid="library.classpath"/>
+      <path refid="dependentmodule.classpath"/>
+    </path>
+
+    <!-- RMIC should generate stubs compatible with Java 1.2+ -->
+    <property name="rmic.stubVersion" value="1.2"/>
+
+    <!-- classpath and local.classpath must have a value using with a path -->
+    <property name="classpath" value=""/>
+    <property name="local.classpath" value=""/>
+
+    <!-- The classpath required to build classes. -->
+    <path id="javac.classpath">
+      <pathelement path="${classpath}"/>
+      <pathelement path="${local.classpath}"/>
+      <path refid="thirdparty.classpath"/>
+    </path>
+
+    <!-- The classpath required to build javadocs. -->
+    <path id="javadoc.classpath">
+      <path refid="javac.classpath"/>
+    </path>
+
+    <!-- Packages to include when generating api documentation -->
+    <property name="javadoc.packages" value="org.jnp.*"/>
+
+    <!-- Override JUnit defaults -->
+    <property name="junit.timeout" value="240000"/> <!-- 4 minutes -->
+    <property name="junit.batchtest.todir" value="${build.reports}"/>
+    <property name="junit.jvm.options" value="-Ddummy"/>
+  </target>
+
+
+  <!-- ================================================================== -->
+  <!-- Compile                                                            -->
+  <!-- ================================================================== -->
+
+  <!-- 
+     | Compile everything.
+     |
+     | This target should depend on other compile-* targets for each 
+     | different type of compile that needs to be performed, short of
+     | documentation compiles.
+   -->
+
+  <target name="compile"
+    description="Compile all source files."
+    depends="compile-parsers,compile-classes,
+compile-rmi,
+compile-etc"/>
+
+  <!-- Compile parsers -->
+  <target name="compile-parsers" depends="init">
+      <property name="build.parsers" value="${module.output}/gen-parsers"/>
+    <mkdir dir="${build.parsers}/org/jboss/security/auth/login"/>
+
+     <echo>BASE=${basedir}</echo>
+     <echo>PROJECTROOT=${project.root}</echo>
+
+    <!-- Sun JAAS config file parser -->
+    <javacc target="${source.java}/org/jboss/security/auth/login/SunConfigParser.jj"
+      outputdirectory="${build.parsers}/org/jboss/security/auth/login"
+      javacchome="${sun.javacc.lib}"
+      static="false"/>
+  </target>
+
+  <!-- Compile all class files -->
+  <target name="compile-classes" depends="init">
+    <mkdir dir="${build.classes}"/>
+
+    <javac destdir="${build.classes}"
+      optimize="${javac.optimize}"
+      target="${javac.target}"
+      source="${javac.source}"
+      debug="${javac.debug}"
+      depend="${javac.depend}"
+      verbose="${javac.verbose}"
+      deprecation="${javac.deprecation}"
+      includeAntRuntime="${javac.include.ant.runtime}"
+      includeJavaRuntime="${javac.include.java.runtime}"
+      includes="${javac.includes}"
+      excludes="${javac.excludes}"
+      failonerror="${javac.fail.onerror}">
+      <src path="${source.java}"/>
+      <src path="${build.parsers}"/>
+      <classpath refid="javac.classpath"/>
+    </javac>
+  </target>
+
+  <!-- Compile RMI stubs -->
+  <target name="compile-rmi" depends="compile-classes">
+    <mkdir dir="${build.gen-src}"/>
+    <rmic base="${build.classes}"
+      sourcebase="${build.gen-src}"
+      verify="${rmic.verify}"
+      iiop="${rmic.iiop}"
+      iiopopts="${rmic.iiopops}"
+      idl="${rmic.idl}"
+      idlopts="${rmic.idlops}"
+      debug="${rmic.debug}"
+      stubVersion="${rmic.stubVersion}">
+      <classpath refid="javac.classpath"/>
+      <include name="${rmic.includes}"/>
+      <exclude name="${rmic.excludes}"/>
+
+      <include name="**/NamingServer.class"/>
+    </rmic>
+  </target>
+
+  <!-- Compile manifests -->
+  <target name="compile-etc" depends="init">
+    <mkdir dir="${build.etc}"/>
+    <copy todir="${build.etc}" filtering="yes">
+      <fileset dir="${source.etc}">
+        <include name="**"/>
+      </fileset>
+    </copy>
+  </target>
+
+
+  <!-- ================================================================== -->
+  <!-- Archives                                                           -->
+  <!-- ================================================================== -->
+
+  <!-- 
+     | Build all jar files.
+   -->
+  <target name="jars" description="Builds all jar files."
+    depends="_buildmagic:build-bypass-check"
+    unless="build-bypass.on">
+
+    <call target="compile"/>
+
+    <mkdir dir="${build.lib}"/>
+
+    <patternset id="jbosssx-includes">
+      <include name="org/jboss/crypto/**"/>
+      <include name="org/jboss/security/auth/**"/>
+      <include name="org/jboss/security/jce/**"/>
+      <include name="org/jboss/security/jndi/**"/>
+      <include name="org/jboss/security/plugins/**"/>
+      <include name="org/jboss/security/propertyeditor/**"/>
+      <include name="org/jboss/security/ssl/**"/>
+    </patternset>
+
+    <!-- Build jbosssx-server.jar -->
+    <jar jarfile="${build.lib}/jbosssx-server.jar"
+      manifest="${build.etc}/default.mf">
+      <fileset dir="${build.classes}">
+        <patternset refid="jbosssx-includes" />
+      </fileset>
+    </jar>
+    
+
+    <!-- Update the build marker to allow bypassing -->
+    <touch file="${build-bypass.marker}"/>
+
+  </target>
+
+  <!-- ================================================================== -->
+  <!-- Install & Release                                                  -->
+  <!-- ================================================================== -->
+
+  <target name="install"
+    description="Install the structure for a release."
+    depends="all, _buildmagic:install:default"/>
+
+  <target name="release" depends="install"/>
+
+  <target name="release-zip"
+    description="Builds a ZIP distribution."
+    depends="release, _buildmagic:release:zip"/>
+
+  <target name="release-tar"
+    description="Builds a TAR distribution."
+    depends="release, _buildmagic:release:tar"/>
+
+  <target name="release-tgz"
+    description="Builds a TAR-GZ distribution."
+    depends="release, _buildmagic:release:tgz"/>
+
+  <target name="release-all"
+    description="Builds a distribution for each archive type."
+    depends="release-zip, release-tgz"/>
+
+
+  <!-- ================================================================== -->
+  <!-- Cleaning                                                           -->
+  <!-- ================================================================== -->
+
+  <!-- Clean up all build output -->
+  <target name="clean"
+    description="Cleans up most generated files."
+    depends="_buildmagic:clean">
+  </target>
+
+  <!-- Clean up all generated files -->
+  <target name="clobber"
+    description="Cleans up all generated files."
+    depends="_buildmagic:clobber, clean">
+  </target>
+
+
+  <!-- ================================================================== -->
+  <!-- Misc.                                                              -->
+  <!-- ================================================================== -->
+
+  <target name="main" depends="most"
+    description="Executes the default target (most)."/>
+
+  <target name="all" depends="jars, docs"
+    description="Builds everything."/>
+
+  <target name="most" depends="jars"
+    description="Builds almost everything."/>
+
+  <target name="help"
+    description="Show this help message."
+    depends="_buildmagic:help:standard"/>
+
+</project>

Added: trunk/security/src/etc/default.mf
===================================================================
--- trunk/security/src/etc/default.mf	                        (rev 0)
+++ trunk/security/src/etc/default.mf	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Created-By: @java.vm.version@ (@java.vm.vendor@)
+Specification-Title: @specification.title@
+Specification-Version: @specification.version@
+Specification-Vendor: @specification.vendor@
+Implementation-Title: @implementation.title@
+Implementation-URL: @implementation.url@
+Implementation-Version: @implementation.version@
+Implementation-Vendor: @implementation.vendor@
+Implementation-Vendor-Id: @implementation.vendor.id@

Added: trunk/security/src/main/org/jboss/crypto/CipherClientSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/CipherClientSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/CipherClientSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,67 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.Socket;
+import java.rmi.server.RMIClientSocketFactory;
+ 
+
+/** An implementation of RMIClientSocketFactory that uses the JCE Cipher
+ with an SRP session key to create an encrypted stream.
+
+ at author  Scott.Stark at jboss.org
+ at version $Revision: 58708 $
+*/
+public class CipherClientSocketFactory implements RMIClientSocketFactory, Serializable
+{
+   private static final long serialVersionUID = -6412485012870705607L;
+
+   /** Creates new CipherClientSocketFactory */
+   public CipherClientSocketFactory()
+   {
+   }
+
+   /** Create a client socket connected to the specified host and port.
+   * @param host - the host name
+   * @param port - the port number
+   * @return a socket connected to the specified host and port.
+   * @exception IOException if an I/O error occurs during socket creation.
+   */
+   public Socket createSocket(String host, int port)
+      throws IOException
+   {
+      CipherSocket socket = null;
+      return socket;
+   }
+
+   public boolean equals(Object obj)
+   {
+      return obj instanceof CipherClientSocketFactory;
+   }
+   public int hashCode()
+   {
+      return getClass().getName().hashCode();
+   }
+
+}

Added: trunk/security/src/main/org/jboss/crypto/CipherServerSocket.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/CipherServerSocket.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/CipherServerSocket.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,53 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import javax.crypto.SecretKey;
+
+/**
+ *
+ * @author  Scott.Stark at jboss.org
+ */
+public class CipherServerSocket extends ServerSocket
+{
+   String algorithm;
+   SecretKey key;
+
+   /** Creates a new instance of CipherServerSocket */
+   public CipherServerSocket(int port, int backlog,
+      InetAddress bindAddr, String algorithm, SecretKey key) throws IOException
+   {
+      super(port, backlog, bindAddr);
+      this.algorithm = algorithm;
+      this.key = key;
+   }
+
+   public Socket accept() throws IOException
+   {
+      Socket s = super.accept();
+      return new CipherSocket(s, algorithm, key);
+   }
+}

Added: trunk/security/src/main/org/jboss/crypto/CipherServerSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/CipherServerSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/CipherServerSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,75 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.rmi.server.RMIServerSocketFactory;
+
+
+/** An implementation of RMIServerSocketFactory that uses a
+ DomainServerSocketFactory for its implementation. This class is just an
+ adaptor from the RMIServerSocketFactory to the DomainServerSocketFactory.
+
+ This class is not suitable for RMI object that require a Serializable socket
+ factory like activatable services. The reason for this limitation is that
+ a SecurityDomain is not serializable due to its association with a local
+ KeyStore.
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 37459 $
+*/
+public class CipherServerSocketFactory implements RMIServerSocketFactory
+{
+
+   /** Creates new RMISSLServerSocketFactory */
+   public CipherServerSocketFactory()
+   {
+   }
+
+
+   /**
+    * Create a server socket on the specified port (port 0 indicates
+    * an anonymous port).
+    * @param  port the port number
+    * @return the server socket on the specified port
+    * @exception IOException if an I/O error occurs during server socket
+    * creation
+    */
+   public ServerSocket createServerSocket(int port)
+      throws IOException
+   {
+      CipherServerSocket socket = null;
+      return socket;
+   }
+
+   public boolean equals(Object obj)
+   {
+      return obj instanceof CipherServerSocketFactory;
+   }
+   public int hashCode()
+   {
+      return getClass().getName().hashCode();
+   }
+}

Added: trunk/security/src/main/org/jboss/crypto/CipherSocket.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/CipherSocket.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/CipherSocket.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,104 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.Arrays;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.SecretKey;
+
+/**
+ *
+ * @author  Scott.Stark at jboss.org
+ */
+public class CipherSocket extends Socket
+{
+   private Cipher cipher;
+   private Socket delegate;
+   String algorithm;
+   SecretKey key;
+
+   /** Creates a new instance of CipherSocket */
+   public CipherSocket(String host, int port, String algorithm, SecretKey key)
+      throws IOException
+   {
+      super(host, port);
+      this.algorithm = algorithm;
+      this.key = key;
+   }
+   public CipherSocket(Socket delegate, String algorithm, SecretKey key)
+      throws IOException
+   {
+      this.delegate = delegate;
+      this.algorithm = algorithm;
+      this.key = key;
+   }
+
+   public InputStream getInputStream() throws IOException
+   {
+      InputStream is = delegate == null ? super.getInputStream() : delegate.getInputStream();
+      Cipher cipher = null;
+      try
+      {
+         cipher = Cipher.getInstance(algorithm);
+         int size = cipher.getBlockSize();
+         byte[] tmp = new byte[size];
+         Arrays.fill(tmp, (byte)15);
+         IvParameterSpec iv = new IvParameterSpec(tmp);
+         cipher.init(Cipher.DECRYPT_MODE, key, iv);
+      }
+      catch(Exception e)
+      {
+         e.printStackTrace();
+         throw new IOException("Failed to init cipher: "+e.getMessage());
+      }
+      CipherInputStream cis = new CipherInputStream(is, cipher);
+      return cis;
+   }
+
+   public OutputStream getOutputStream() throws IOException
+   {
+      OutputStream os = delegate == null ? super.getOutputStream() : delegate.getOutputStream();
+      Cipher cipher = null;
+      try
+      {
+         cipher = Cipher.getInstance(algorithm);
+         int size = cipher.getBlockSize();
+         byte[] tmp = new byte[size];
+         Arrays.fill(tmp, (byte)15);
+         IvParameterSpec iv = new IvParameterSpec(tmp);
+         cipher.init(Cipher.ENCRYPT_MODE, key, iv);
+      }
+      catch(Exception e)
+      {
+         throw new IOException("Failed to init cipher: "+e.getMessage());
+      }
+      CipherOutputStream cos = new CipherOutputStream(os, cipher);
+      return cos;
+   }
+}

Added: trunk/security/src/main/org/jboss/crypto/digest/DigestCallback.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/digest/DigestCallback.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/digest/DigestCallback.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,55 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto.digest;
+
+import java.util.Map;
+import java.security.MessageDigest;
+
+/**
+ * An interface that can be used to augment the behavior of a digest hash.
+ * One example usecase is with the password based login modules to
+ * modify the behavior of the hashing to introduce prefix/suffix salts.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public interface DigestCallback
+{
+   /** Pass through access to the login module options. When coming from a
+    * login module this includes the following keys:
+    * javax.security.auth.login.name - for the username
+    * javax.security.auth.login.password - for the String password
+    */
+   public void init(Map options);
+   /**
+    * Pre-hash callout to allow for content before the password. Any content
+    * should be added using the MessageDigest update methods.
+    * @param digest - the security digest being used for the one-way hash
+    */ 
+   public void preDigest(MessageDigest digest);
+   /** Post-hash callout afer the password has been added to allow for content
+    * after the password has been added. Any content should be added using the
+    * MessageDigest update methods.
+    * @param digest - the security digest being used for the one-way hash
+    */
+   public void postDigest(MessageDigest digest);
+}

Added: trunk/security/src/main/org/jboss/crypto/digest/SHAInterleave.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/digest/SHAInterleave.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/digest/SHAInterleave.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,146 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto.digest;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.MessageDigestSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+
+/** The SHA_Interleave algorithm as described in section 3.1 of RFC2945. This
+ needs an SHA MessageDigest provider to function.
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 37459 $
+*/
+public class SHAInterleave extends MessageDigestSpi
+{
+   private static final int SHA_HASH_LEN = 20;
+
+   private ByteArrayOutputStream evenBytes;
+   private ByteArrayOutputStream oddBytes;
+   private int count;
+   private boolean skipLeadingZeros;
+   private MessageDigest sha;
+
+   /** Creates a new instance of SHAInterleave
+    @exception ProviderException thrown if MessageDigest.getInstance("SHA")
+    throws a NoSuchAlgorithmException.
+    */
+   public SHAInterleave()
+   {
+      try
+      {
+         sha = MessageDigest.getInstance("SHA");
+      }
+      catch(NoSuchAlgorithmException e)
+      {
+         throw new ProviderException("Failed to obtain SHA MessageDigest");
+      }
+      evenBytes = new ByteArrayOutputStream();
+      oddBytes = new ByteArrayOutputStream();
+      engineReset();
+   }
+
+   protected int engineGetDigestLength()
+   {
+      return 2 * SHA_HASH_LEN;
+   }
+
+   /**
+    * Completes the digest computation by performing final
+    * operations such as padding. Once <code>engineDigest</code> has
+    * been called, the engine should be reset (see
+    * {@link #engineReset() engineReset}).
+    * Resetting is the responsibility of the
+    * engine implementor.
+    *
+    * @return the array of bytes for the resulting digest value.
+    */
+   protected byte[] engineDigest()
+   {
+      byte[] E = evenBytes.toByteArray();
+      byte[] G = sha.digest(E);
+      // If the count is odd, drop the first byte
+      byte[] F = oddBytes.toByteArray();
+      int offset = 0;
+      if( count % 2 == 1 )
+         offset = 1;
+      sha.reset();
+      sha.update(F, offset, F.length-offset);
+      byte[] H = sha.digest();
+      int length = G.length + H.length;
+      byte[] digest = new byte[length];
+      for(int i = 0; i < G.length; ++i)
+         digest[2 * i] = G[i];
+      for(int i = 0; i < H.length; ++i)
+         digest[2 * i + 1] = H[i];
+      engineReset();
+      return digest;
+   }
+
+   /**
+    * Resets the digest for further use.
+    */
+   protected void engineReset()
+   {
+      skipLeadingZeros = true;
+      count = 0;
+      evenBytes.reset();
+      oddBytes.reset();
+      sha.reset();
+   }
+
+   /**
+    * Updates the digest using the specified byte.
+    *
+    * @param input the byte to use for the update.
+    */
+   protected void engineUpdate(byte input)
+   {
+      if( skipLeadingZeros == true && input == 0 )
+         return;
+      skipLeadingZeros = false;
+      if( count % 2 == 0 )
+         evenBytes.write(input);
+      else
+         oddBytes.write(input);
+      count ++;
+   }
+
+   /**
+    * Updates the digest using the specified array of bytes,
+    * starting at the specified offset.
+    *
+    * @param input the array of bytes to use for the update.
+    * @param offset the offset to start from in the array of bytes.
+    * @param len the input of bytes to use, starting at
+    * <code>offset</code>.
+    */
+   protected void engineUpdate(byte[] input, int offset, int len)
+   {
+      for(int i = offset; i < offset+len; i ++)
+         engineUpdate(input[i]);
+   }
+
+}

Added: trunk/security/src/main/org/jboss/crypto/digest/SHAReverseInterleave.java
===================================================================
--- trunk/security/src/main/org/jboss/crypto/digest/SHAReverseInterleave.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/crypto/digest/SHAReverseInterleave.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,166 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.crypto.digest;
+
+import java.io.ByteArrayOutputStream;
+import java.security.MessageDigest;
+import java.security.MessageDigestSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException; 
+
+/** An alternate SHA Interleave algorithm as implemented in the SRP
+ distribution. This version reverses the even and odd byte streams before
+ performing the SHA digest.
+
+ This product includes software developed by Tom Wu and Eugene
+ Jhong for the SRP Distribution (http://srp.stanford.edu/srp/).
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 58708 $
+*/
+public class SHAReverseInterleave extends MessageDigestSpi
+{
+   private static final int SHA_HASH_LEN = 20;
+
+   private ByteArrayOutputStream evenBytes;
+   private ByteArrayOutputStream oddBytes;
+   private int count;
+   private boolean skipLeadingZeros;
+   private MessageDigest sha;
+
+   /** Creates a new instance of SHAReverseInterleave
+    @exception ProviderException thrown if MessageDigest.getInstance("SHA")
+    throws a NoSuchAlgorithmException.
+    */
+   public SHAReverseInterleave()
+   {
+      try
+      {
+         sha = MessageDigest.getInstance("SHA");
+      }
+      catch(NoSuchAlgorithmException e)
+      {
+         throw new ProviderException("Failed to obtain SHA MessageDigest");
+      }
+      evenBytes = new ByteArrayOutputStream();
+      oddBytes = new ByteArrayOutputStream();
+      engineReset();
+   }
+
+   protected int engineGetDigestLength()
+   {
+      return 2 * SHA_HASH_LEN;
+   }
+
+   /**
+    * Completes the digest computation by performing final
+    * operations such as padding. Once <code>engineDigest</code> has
+    * been called, the engine should be reset (see
+    * {@link #engineReset() engineReset}).
+    * Resetting is the responsibility of the
+    * engine implementor.
+    *
+    * @return the array of bytes for the resulting digest value.
+    */
+   protected byte[] engineDigest()
+   {
+      byte[] E = evenBytes.toByteArray();
+      // If the count is odd, drop the first byte
+      int length = E.length;
+      if( count % 2 == 1 )
+         length --;
+      // Reverse the order of the even bytes
+      byte[] tmp = new byte[length];
+      for(int i = 0; i < length; i ++)
+      {
+         tmp[i] = E[E.length - i - 1];
+         System.out.println("E["+i+"] = "+tmp[i]);
+      }
+      E = tmp;
+      byte[] G = sha.digest(E);
+
+      byte[] F = oddBytes.toByteArray();
+      // Reverse the order of the even bytes
+      tmp = new byte[F.length];
+      for(int i = 0; i < F.length; i ++)
+      {
+         tmp[i] = F[F.length - i - 1];
+         System.out.println("F["+i+"] = "+tmp[i]);
+      }
+      F = tmp;
+      sha.reset();
+      byte[] H = sha.digest(F);
+      length = G.length + H.length;
+      byte[] digest = new byte[length];
+      for(int i = 0; i < G.length; ++i)
+         digest[2 * i] = G[i];
+      for(int i = 0; i < H.length; ++i)
+         digest[2 * i + 1] = H[i];
+      engineReset();
+      return digest;
+   }
+
+   /**
+    * Resets the digest for further use.
+    */
+   protected void engineReset()
+   {
+      skipLeadingZeros = true;
+      count = 0;
+      evenBytes.reset();
+      oddBytes.reset();
+      sha.reset();
+   }
+
+   /**
+    * Updates the digest using the specified byte.
+    *
+    * @param input the byte to use for the update.
+    */
+   protected void engineUpdate(byte input)
+   {
+      if( skipLeadingZeros == true && input == 0 )
+         return;
+      skipLeadingZeros = false;
+      if( count % 2 == 0 )
+         evenBytes.write(input);
+      else
+         oddBytes.write(input);
+      count ++;
+   }
+
+   /**
+    * Updates the digest using the specified array of bytes,
+    * starting at the specified offset.
+    *
+    * @param input the array of bytes to use for the update.
+    * @param offset the offset to start from in the array of bytes.
+    * @param len the input of bytes to use, starting at
+    * <code>offset</code>.
+    */
+   protected void engineUpdate(byte[] input, int offset, int len)
+   {
+      for(int i = offset; i < offset+len; i ++)
+         engineUpdate(input[i]);
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/AbstractSecurityProxy.java
===================================================================
--- trunk/security/src/main/org/jboss/security/AbstractSecurityProxy.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/AbstractSecurityProxy.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,313 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import javax.ejb.EJBContext;
+
+/**
+ * An abstract implementation of SecurityProxy that wraps a non-SecurityProxy
+ * object. Subclasses of this class are used to create a SecurityProxy given
+ * a security delegate that implements methods in the EJB home or remote
+ * interface for security checks. This allows custom security classes to be
+ * written without using a JBoss specific interface. It also allows the security
+ * delegate to follow a natural proxy pattern implementation.
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public abstract class AbstractSecurityProxy implements SecurityProxy
+{
+   /** The HashMap<Method, Method> from the EJB interface methods to the
+    * corresponding delegate method
+    */
+   private HashMap methodMap;
+   /** The optional setContext delegate method */
+   private Method setContextMethod;
+   /** The optional setContext delegate method */
+   private Method setBeanMethod;
+   /** The optional setContext delegate method */
+   protected Object delegate;
+   /** Flag which sets whether the method mapping will be performed in a strict
+    * fashion. The proxy delegate must provide an implementation of all methods.
+    * If set to 'true', a security exception will be thrown during
+    * initialisation if a method is found for which the delegate doesn't have
+    * a matching method. This defaults to false and is obtained via reflection
+    * on the proxy delegate's 'boolean isStrict()' method.
+    */
+   protected boolean strict = false;
+
+   AbstractSecurityProxy(Object delegate)
+   {
+      this.delegate = delegate;
+      methodMap = new HashMap();
+   }
+
+   /**
+    * Subclasses implement this method to actually invoke the given home
+    * method on the proxy delegate.
+    *
+    * @param m, the delegate method that was mapped from the ejb home method.
+    * @param args, the method invocation arguments.
+    * @param delegate, the proxy delegate object associated with the
+    *    AbstractSecurityProxy
+    * 
+    * @see invokeHome(Method, Object[])
+    */
+   protected abstract void invokeHomeOnDelegate(Method m, Object[] args,
+      Object delegate) throws Exception;
+
+   /**
+    * Subclasses implement this method to actually invoke the given remote
+    * method on the proxy delegate.
+    *
+    * @param m, the delegate method that was mapped from the ejb remote method.
+    * @param args, the method invocation arguments.
+    * @param delegate, the proxy delegate object associated with the AbstractSecurityProxy
+    * 
+    * @see invoke(Method, Object[], Object)
+    */
+   protected abstract void invokeOnDelegate(Method m, Object[] args, Object delegate)
+      throws Exception;
+
+   /**
+    *
+    * This version invokes init(beanHome, beanRemote, null, null, securityMgr)
+    *
+    * @see #init(Class, Class, Class, Class, Object)
+    * @param beanHome, the class for the EJB home interface
+    * @param beanRemote, the class for the EJB remote interface
+    * @param securityMgr, The security manager instance assigned to the container.
+    * It is not used by this class.
+    */
+   public void init(Class beanHome, Class beanRemote, Object securityMgr)
+      throws InstantiationException
+   {
+      init(beanHome, beanRemote, null, null, securityMgr);
+   }
+
+   /** This method is called by the container SecurityInterceptor to intialize
+    * the proxy with the EJB home and remote interface classes that the
+    * container is housing. This method creates a mapping from the home and
+    * remote classes to the proxy delegate instance. The mapping is based on
+    * method name and paramter types. In addition, the proxy delegate is
+    * inspected for a setEJBContext(EJBContext) and a setBean(Object) method
+    * so that the active EJBContext and EJB instance can be passed to the
+    * delegate prior to method invocations.
+    *
+    * @param beanHome The EJB remote home interface class
+    * @param beanRemote The EJB remote interface class
+    * @param beanLocalHome The EJB local home interface class
+    * @param beanLocal The EJB local interface class
+    * @param securityMgr The security manager from the security domain
+    * @throws InstantiationException
+    */
+   public void init(Class beanHome, Class beanRemote,
+      Class beanLocalHome, Class beanLocal, Object securityMgr)
+      throws InstantiationException
+   {
+      // Get any methods from the bean home interface
+      mapHomeMethods(beanHome);
+      // Get any methods from the bean local home interface
+      mapHomeMethods(beanLocalHome);
+      // Get any methods from the bean remote interface
+      mapRemoteMethods(beanRemote);
+      // Get any methods from the bean local interface
+      mapRemoteMethods(beanLocal);
+      // Get the setEJBContext(EJBContext) method
+      try
+      {
+         Class[] parameterTypes = {EJBContext.class};
+         setContextMethod = delegate.getClass().getMethod("setEJBContext", parameterTypes);
+      }
+      catch(Exception ignore)
+      {
+      }
+
+      // Get the setBean(Object) method
+      try
+      {
+         Class[] parameterTypes = {Object.class};
+         setBeanMethod = delegate.getClass().getMethod("setBean", parameterTypes);
+      }
+      catch(Exception ignore)
+      {
+      }
+
+      // Check for a boolean isStrict() strict flag accessor
+      try
+      {
+         Class[] parameterTypes = {};
+         Object[] args = {};
+         Method isStrict = delegate.getClass().getMethod("isStrict", parameterTypes);
+         Boolean flag = (Boolean) isStrict.invoke(delegate, args);
+         strict = flag.booleanValue();
+      }
+      catch(Exception ignore)
+      {
+      }
+   }
+
+   /** Called by the SecurityProxyInterceptor prior to a method invocation
+    * to set the context for the call.
+    *
+    * @param ctx the bean's EJBContext
+    */
+   public void setEJBContext(EJBContext ctx)
+   {
+      if(setContextMethod != null)
+      {
+         Object[] args = {ctx};
+         try
+         {
+            setContextMethod.invoke(delegate, args);
+         }
+         catch(Exception e)
+         {
+            e.printStackTrace();
+         }
+      }
+   }
+
+   /** Called by the SecurityProxyInterceptor to allow the proxy delegate to
+    * perform a security check of the indicated home interface method.
+    *
+    * @param m, the EJB home interface method
+    * @param args, the method arguments
+    */
+   public void invokeHome(final Method m, Object[] args)
+      throws Exception
+   {
+      Method delegateMethod = (Method)methodMap.get(m);
+      if( delegateMethod != null )
+         invokeHomeOnDelegate(delegateMethod, args, delegate);
+   }
+
+   /**
+    * Called by the SecurityProxyInterceptor to allow the proxy delegate to perform
+    * a security check of the indicated remote interface method.
+    * @param m, the EJB remote interface method
+    * @param args, the method arguments
+    * @param bean, the EJB bean instance
+    */
+   public void invoke(final Method m, final Object[] args, final Object bean)
+      throws Exception
+   {
+      Method delegateMethod = (Method)methodMap.get(m);
+      if( delegateMethod != null )
+      {
+         if( setBeanMethod != null )
+         {
+            Object[] bargs = {bean};
+            try
+            {
+               setBeanMethod.invoke(delegate, bargs);
+            }
+            catch(Exception e)
+            {
+               e.printStackTrace();
+               throw new SecurityException("Failed to set bean on proxy" + e.getMessage());
+            }
+         }
+         invokeOnDelegate(delegateMethod, args, delegate);
+      }
+   }
+
+   /** Performs a mapping from the methods declared in the beanHome class to
+    * the proxy delegate class. This allows the methods to be either named
+    * the same as the home interface method "create(...)" or as the bean
+    * class method "ejbCreate(...)". This handles both local home and
+    * remote home interface methods.
+    */
+   protected void mapHomeMethods(Class beanHome)
+   {
+      if( beanHome == null )
+         return;
+
+      Class delegateClass = delegate.getClass();
+      Method[] methods = beanHome.getMethods();
+      for(int m = 0; m < methods.length; m++)
+      {
+         // Check for ejbCreate... methods
+         Method hm = methods[m];
+         Class[] parameterTypes = hm.getParameterTypes();
+         String name = hm.getName();
+         name = "ejb" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
+         try
+         {
+            Method match = delegateClass.getMethod(name, parameterTypes);
+            methodMap.put(hm, match);
+         }
+         catch(NoSuchMethodException e)
+         {
+            // Try for the home interface name without the ejb prefix
+            name = hm.getName();
+            try
+            {
+               Method match = delegateClass.getMethod(name, parameterTypes);
+               methodMap.put(hm, match);
+            }
+            catch(NoSuchMethodException e2)
+            {
+               if( strict )
+               {
+                  String msg = "Missing home method:" + hm + " in delegate";
+                  throw new SecurityException(msg);
+               }
+            }
+         }
+      }
+   }
+
+   /** Performs a mapping from the methods declared in the beanRemote class to
+    * the proxy delegate class. This handles both local and remote interface
+    * methods.
+    */
+   protected void mapRemoteMethods(Class beanRemote)
+   {
+      if( beanRemote == null )
+         return;
+
+      Class delegateClass = delegate.getClass();
+      Method[] methods = beanRemote.getMethods();
+      for(int m = 0; m < methods.length; m++)
+      {
+         Method rm = methods[m];
+         Class[] parameterTypes = rm.getParameterTypes();
+         String name = rm.getName();
+         try
+         {
+            Method match = delegateClass.getMethod(name, parameterTypes);
+            methodMap.put(rm, match);
+         }
+         catch(NoSuchMethodException e)
+         {
+            if( strict )
+            {
+               String msg = "Missing method:" + rm + " in delegate";
+               throw new SecurityException(msg);
+            }
+         }
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/AuthorizationManagerFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/AuthorizationManagerFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/AuthorizationManagerFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,55 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.security;
+
+import javax.management.MBeanServer;
+
+import org.jboss.logging.Logger;
+import org.jboss.mx.util.MBeanProxyExt;
+import org.jboss.mx.util.MBeanServerLocator;
+import org.jboss.security.plugins.AuthorizationManagerServiceMBean;
+
+//$Id: AuthorizationManagerFactory.java 46208 2006-07-11 19:39:14Z asaldhana $
+
+/**
+ *  Factory for obtaining the AuthorizationManager
+ *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
+ *  @since  Jan 4, 2006 
+ *  @version $Revision: 46208 $
+ */
+public class AuthorizationManagerFactory
+{
+   private static Logger log = Logger.getLogger(AuthorizationManagerFactory.class);
+   
+   public static AuthorizationManager getAuthorizationManager( String securityDomain)
+   {
+      log.debug("Enter getAuthorizationManager with securityDomain=" + securityDomain);
+      AuthorizationManager manager = null; 
+      MBeanServer server = MBeanServerLocator.locateJBoss(); 
+      AuthorizationManagerServiceMBean mbean =(AuthorizationManagerServiceMBean)
+                             MBeanProxyExt.create(AuthorizationManagerServiceMBean.class,
+                                   AuthorizationManagerServiceMBean.OBJECT_NAME, server);
+      manager = mbean.getAuthorizationManager(securityDomain); 
+      log.debug("return getAuthorizationManager=" + manager);
+      return manager;
+   }
+}

Added: trunk/security/src/main/org/jboss/security/SecurityActions.java
===================================================================
--- trunk/security/src/main/org/jboss/security/SecurityActions.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/SecurityActions.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,81 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Priviledged actions for this package
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 40069 $
+ */
+class SecurityActions
+{
+   interface SystemPropertyAction
+   {
+      SystemPropertyAction PRIVILEGED = new SystemPropertyAction()
+      {
+         public String getProperty(final String name, final String defaultValue)
+         {
+            String prop = (String) AccessController.doPrivileged(
+               new PrivilegedAction()
+               {
+                  public Object run()
+                  {
+                     String p = System.getProperty(name, defaultValue);
+                     return p;
+                  }
+               }
+            );
+            return prop;
+         }
+      };
+
+      SystemPropertyAction NON_PRIVILEGED = new SystemPropertyAction()
+      {
+         public String getProperty(final String name, final String defaultValue)
+         {
+            String prop = System.getProperty(name, defaultValue);
+            return prop;
+         }
+      };
+
+      String getProperty(final String name, final String defaultValue);
+   }
+
+   static String getProperty(final String name, final String defaultValue)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      String prop;
+      if( sm != null )
+      {
+         prop = SystemPropertyAction.PRIVILEGED.getProperty(name, defaultValue);
+      }
+      else
+      {
+         prop = SystemPropertyAction.NON_PRIVILEGED.getProperty(name, defaultValue);
+      }
+      return prop;
+   }
+}

Added: trunk/security/src/main/org/jboss/security/SubjectSecurityProxy.java
===================================================================
--- trunk/security/src/main/org/jboss/security/SubjectSecurityProxy.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/SubjectSecurityProxy.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,155 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.lang.reflect.Method;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+import javax.security.auth.Subject;
+
+import org.jboss.security.SubjectSecurityManager;
+
+/** A subclass of AbstractSecurityProxy that executes as the currently
+ authenticated subject within the invokeHomeOnDelegate and invokeOnDelegate
+ methods. The current subject is accessed via the security manager passed
+ to the init() method, which must be an instance of SubjectSecurityManager.
+ This results in AccessController.checkPermission() calls made from within the
+ security delegate methods to be based on the Subject's permissions.
+
+ This is just an experiment with the JAAS Subject based permissions.
+
+ @see javax.security.auth.Subject
+  @see org.jboss.security.SubjectSecurityManager
+
+ @author Scott.Stark at jboss.org
+ @version $Revision: 37459 $
+ */
+public class SubjectSecurityProxy extends AbstractSecurityProxy
+{
+   private SubjectSecurityManager subjectSecurityManager;
+
+   SubjectSecurityProxy(Object delegate)
+   {
+      super(delegate);
+   }
+
+   public void init(Class beanHome, Class beanRemote, Object securityMgr)
+      throws InstantiationException
+   {
+      init(beanHome, beanRemote, null, null, securityMgr);
+   }
+
+   public void init(Class beanHome, Class beanRemote,
+      Class beanLocalHome, Class beanLocal, Object securityMgr)
+      throws InstantiationException
+   {
+      if ((securityMgr instanceof SubjectSecurityManager) == false)
+      {
+         String msg = "SubjectSecurityProxy requires a SubjectSecurityManager"
+            + " instance, securityMgr=" + securityMgr;
+         throw new InstantiationException(msg);
+      }
+      subjectSecurityManager = (SubjectSecurityManager) securityMgr;
+      super.init(beanHome, beanRemote, beanLocalHome, beanLocal, securityMgr);
+   }
+
+   protected void invokeHomeOnDelegate(final Method m, final Object[] args, final Object delegate)
+      throws SecurityException
+   {   // Get authenticated subject and invoke invokeAsSubject in Subject.doAsPrivaledged() block...
+      final Subject subject = subjectSecurityManager.getActiveSubject();
+      if (subject == null)
+         throw new SecurityException("No subject associated with secure proxy");
+
+      try
+      {
+         Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
+         {
+            public Object run() throws Exception
+            {
+               m.invoke(delegate, args);
+               return null;
+            }
+         },
+            null
+         );
+      }
+      catch (PrivilegedActionException e)
+      {
+         Throwable t = e.getException();
+         if (t instanceof InvocationTargetException)
+         {
+            t = ((InvocationTargetException) t).getTargetException();
+         }
+         else if (t instanceof UndeclaredThrowableException)
+         {
+            t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
+         }
+         if (t instanceof SecurityException)
+            throw (SecurityException) t;
+         t.printStackTrace();
+         throw new SecurityException("Unexpected error during security proxy execution:" + t.getMessage());
+      }
+   }
+
+   protected void invokeOnDelegate(final Method m, final Object[] args, final Object delegate)
+      throws Exception
+   {   // Get authenticated subject and invoke invokeAsSubject in Subject.doAsPrivaledged() block...
+      final Subject subject = subjectSecurityManager.getActiveSubject();
+      if (subject == null)
+         throw new SecurityException("No subject associated with secure proxy");
+
+      try
+      {
+         Subject.doAsPrivileged(subject, new PrivilegedExceptionAction()
+         {
+            public Object run() throws Exception
+            {
+               m.invoke(delegate, args);
+               return null;
+            }
+         },
+            null
+         );
+      }
+      catch (PrivilegedActionException e)
+      {
+         Throwable t = e.getException();
+         if (t instanceof InvocationTargetException)
+         {
+            // This is a declared exception, just throw it
+            InvocationTargetException ex = (InvocationTargetException) t;
+            t = ex.getTargetException();
+            throw (Exception) t;
+         }
+         else if (t instanceof UndeclaredThrowableException)
+         {
+            t = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
+         }
+         if (t instanceof SecurityException)
+            throw (SecurityException) t;
+         throw new SecurityException("Unexpected error during security proxy execution:" + t.getMessage());
+      }
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/SubjectSecurityProxyFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,42 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security;
+
+import java.io.Serializable;
+
+/** An implementation of SecurityProxyFactory that creates SubjectSecurityProxy
+objects to wrap the raw security proxy objects.
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 58711 $
+*/
+public class SubjectSecurityProxyFactory implements SecurityProxyFactory, Serializable
+{ 
+   private static final long serialVersionUID = 1L;
+
+   public SecurityProxy create(Object proxyDelegate)
+    {
+        SecurityProxy proxy = new SubjectSecurityProxy(proxyDelegate);
+        return proxy;
+    }
+
+}

Added: trunk/security/src/main/org/jboss/security/auth/SystemAuthenticator.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/SystemAuthenticator.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/SystemAuthenticator.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,115 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+ 
+import org.jboss.system.ServiceMBeanSupport;
+
+/** An MBean that requires a JAAS login in order for it to startup. This is
+ * used to require authentication to startup a JBoss instance.
+ *
+ * @version $Revision: 58711 $
+ * @author Scott.Stark at jboss.org
+ */
+public class SystemAuthenticator extends ServiceMBeanSupport
+   implements SystemAuthenticatorMBean
+{
+   /** The Subject that results from the login. Not used currently */
+   private Subject systemSubject;
+   /** The name of the security domain to authenticate under */
+   private String securityDomain;
+   /** The CallbackHandler that knows how to provide Callbacks for the
+      security domain login modules
+    */
+   private CallbackHandler callbackHandler;
+
+   /** Get the name of the security domain used for authentication
+    */
+   public String getSecurityDomain()
+   {
+      return this.securityDomain;
+   }
+
+   /** Set the name of the security domain used for authentication
+    */
+   public void setSecurityDomain(String name)
+   {
+      this.securityDomain = name;
+   }
+
+   /** Get the CallbackHandler to use to obtain the authentication
+    information.
+    @see javax.security.auth.callback.CallbackHandler
+    */
+   public Class getCallbackHandler()
+   {
+      Class clazz = null;
+      if( callbackHandler != null )
+         clazz = callbackHandler.getClass();
+      return clazz;
+   }
+   /** Specify the CallbackHandler to use to obtain the authentication
+    information.
+    @see javax.security.auth.callback.CallbackHandler
+    */
+   public void setCallbackHandler(Class callbackHandlerClass)
+      throws InstantiationException, IllegalAccessException
+   {
+      callbackHandler = (CallbackHandler) callbackHandlerClass.newInstance();
+   }
+
+   protected void startService() throws Exception
+   {
+      try
+      {
+         LoginContext lc = new LoginContext(securityDomain, callbackHandler);
+         lc.login();
+         this.systemSubject = lc.getSubject();
+      }
+      catch(Throwable t)
+      {
+         log.fatal("SystemAuthenticator failed, server will shutdown NOW!", t);
+         LoginException le = new LoginException("SystemAuthenticator failed, msg="+t.getMessage());
+         Thread shutdownThread = new Thread("SystemAuthenticatorExitThread")
+         {
+            public void run()
+            {
+               System.exit(1);
+            }
+         };
+         shutdownThread.start();
+      }
+   }
+
+   protected void stopService() throws Exception
+   {
+      if( systemSubject != null )
+      {
+         LoginContext lc = new LoginContext(securityDomain, systemSubject, callbackHandler);
+         lc.logout();
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/auth/SystemAuthenticatorMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/SystemAuthenticatorMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/SystemAuthenticatorMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,52 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth;
+
+import org.jboss.system.ServiceMBean;
+
+/** An MBean that requires a JAAS login in order for it to startup. This 
+ * cam be used to require a login to startup the JBoss server.
+ *
+ * @version $Revision: 37459 $
+ * @author Scott.Stark at jboss.org
+ */
+public interface SystemAuthenticatorMBean extends ServiceMBean
+{
+   /** Get the name of the security domain used for authentication
+    */
+   public String getSecurityDomain();
+   /** Set the name of the security domain used for authentication
+    */
+   public void setSecurityDomain(String name);
+
+   /** Get the CallbackHandler to use to obtain the authentication
+    information.
+    @see javax.security.auth.callback.CallbackHandler
+    */
+   public Class getCallbackHandler();
+   /** Specify the CallbackHandler to use to obtain the authentication
+    information.
+    @see javax.security.auth.callback.CallbackHandler
+    */
+   public void setCallbackHandler(Class callbackHandlerClass)
+      throws InstantiationException, IllegalAccessException;
+}

Added: trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfig.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfig.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfig.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,279 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.login;
+
+import java.net.URL;
+import java.util.Set;
+import java.util.Iterator;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.security.auth.login.AppConfigurationEntry;
+
+import org.jboss.mx.util.MBeanProxy;
+import org.jboss.security.config.ApplicationPolicy;
+import org.jboss.security.config.PolicyConfig;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.system.server.ServerConfigImplMBean;
+import org.jboss.deployment.DeploymentException;
+
+/** A security config mbean that loads an xml login configuration using the
+ XMLLoginConfig.loadConfig(URL config) operation on start, and unloads
+ the contained login module configurations on stop.
+
+ <server>
+   <mbean code="org.jboss.security.auth.login.DynamicLoginConfig"
+      name="...">
+      <attribute name="AuthConfig">login-config.xml</attribute>
+      <!-- The service which supports dynamic processing of login-config.xml
+         configurations.
+      -->
+      <depends optional-attribute-name="LoginConfigService">
+         jboss.security:service=XMLLoginConfig
+      </depends>
+      <!-- Optionally specify the security mgr service to use when
+         this service is stopped to flush the auth caches of the domains
+         registered by this service.
+      -->
+      <depends optional-attribute-name="SecurityManagerService">
+         jboss.security:service=JaasSecurityManager
+      </depends>
+   </mbean>
+ </server>
+ 
+ @see org.jboss.security.auth.login.XMLLoginConfig
+
+ @author Scott.Stark at jboss.org
+ @author Anil.Saldhana at jboss.org
+ @version $Revision: 46521 $
+ */
+public class DynamicLoginConfig extends ServiceMBeanSupport
+   implements DynamicLoginConfigMBean
+{
+   /** The JAAS login config file resource to load */
+   private String authConf = "login-config.xml";
+   /** The name of the XMLLoginConfig to use to load the login configs */
+   private ObjectName loginConfigService;
+   /** The name of the SecurityMgrService to use for cache flushes */
+   private ObjectName securityMgrService;
+   /** The names of the login module configs loaded during start */
+   private String[] configNames;
+   private PolicyConfig config;
+
+   public DynamicLoginConfig()
+   {
+   }
+
+   public String getName()
+   {
+      return "Dynamic JAAS Login Config";
+   }
+
+   public PolicyConfig getPolicyConfig()
+   {
+      return config;
+   }
+   public void setPolicyConfig(PolicyConfig config)
+   {
+      this.config = config;
+   }
+
+   public ObjectName getLoginConfigService()
+   {
+      return loginConfigService;
+   }
+   /** Get the XMLLoginConfig service to use for loading. This service must
+    * support a String[] loadConfig(URL) operation to load the configurations. 
+    * 
+    * @param serviceName - the XMLLoginConfig service name.
+    */ 
+   public void setLoginConfigService(ObjectName serviceName)
+   {
+      this.loginConfigService = serviceName;
+   }
+
+   public ObjectName getSecurityManagerService()
+   {
+      return securityMgrService;
+   }
+   /** Set the SecurityManagerService used to flush the registered security
+    * domains. This service must support an flushAuthenticationCache(String)
+    * operation to flush the case for the argument security domain. Setting
+    * this triggers the flush of the authentication caches when the service
+    * is stopped.
+    * @param serviceName - the SecurityManagerService service name.
+    */
+   public void setSecurityManagerService(ObjectName serviceName)
+   {
+      this.securityMgrService = serviceName;
+   }
+
+   /** Get the resource path to the JAAS login configuration file to use.
+    */
+   public String getAuthConfig()
+   {
+      return authConf;
+   }
+
+   /** Set the resource path to the JAAS login configuration file to use.
+    The default is "login-config.xml".
+    */
+   public void setAuthConfig(String authConf)
+   {
+      this.authConf = authConf;
+   }
+
+   /** Go through the registered login config names and flush the auth
+    * caches if there is a registered SecurityManagerService.
+    * 
+    * @throws Exception
+    */ 
+   public void flushAuthenticationCaches() throws Exception
+   {
+      if( this.securityMgrService != null && server.isRegistered(securityMgrService))
+      {
+         int count = configNames == null ? 0 : configNames.length;
+         String[] sig = {String.class.getName()};
+         for(int n = 0; n < count; n ++)
+         {
+            Object[] args = {configNames[n]};
+            server.invoke(securityMgrService, "flushAuthenticationCache", args, sig);         
+            log.debug("Flushed domain: "+configNames[n]);
+         }
+      }
+   }
+
+   /** Start the service. This entails loading the AuthConf file contents
+    * using the LoginConfigService.
+    */
+   protected void startService() throws Exception
+   {
+      if( config != null )
+      {
+         log.debug("Using embedded config");
+         Set names = config.getConfigNames();
+         Iterator iter = names.iterator();
+         MBeanServer server = super.getServer();
+         while( iter.hasNext() )
+         {
+            String name = (String) iter.next();
+            ApplicationPolicy aPolicy = config.get(name);
+            if(aPolicy == null)
+               throw new IllegalStateException("Application Policy is null for "+name);
+            
+            AuthenticationInfo info = (AuthenticationInfo)aPolicy.getAuthenticationInfo();
+            AppConfigurationEntry[] entry = info.getAppConfigurationEntry();
+            // addAppConfig(String, AppConfigurationEntry[]);
+            //Object[] args = {name, entry};
+            //String[] sig = {String.class.getName(), entry.getClass().getName()};
+            Object[] args = {name, aPolicy};
+            String[] sig = {String.class.getName(), aPolicy.getClass().getName()};
+            //server.invoke(loginConfigService, "addAppConfig", args, sig);
+            server.invoke(loginConfigService, "addApplicationPolicy", args, sig);
+         }
+         configNames = new String[names.size()];
+         names.toArray(configNames);
+      }
+      else
+      {
+         //JBAS-3422: Ensure that the AuthConf is neither null nor default login-config.xml 
+         if( authConf== null || authConf.length() == 0)
+            throw new IllegalStateException("AuthConf is null. Please " +
+                  "configure an appropriate config resource");
+          
+         // Look for the authConf as resource
+         ClassLoader loader = Thread.currentThread().getContextClassLoader();
+         URL loginConfig = loader.getResource(authConf);
+         if(loginConfig == null)
+         {
+           try
+           {
+             //JBAS-3210: Allow an absolute url
+             loginConfig = new URL(authConf);
+           }
+           catch(Exception e)
+           {
+             loginConfig = null;
+           }
+         }
+         if( loginConfig != null )
+         {
+            validateAuthConfigURL(loginConfig.toExternalForm());
+            log.debug("Using JAAS AuthConfig: "+loginConfig.toExternalForm());
+            MBeanServer server = super.getServer();
+            Object[] args = {loginConfig};
+            String[] sig = {URL.class.getName()};
+            configNames = (String[]) server.invoke(loginConfigService,
+               "loadConfig", args, sig);
+            int count = configNames == null ? 0 : configNames.length;
+            for(int n = 0; n < count; n ++)
+            {
+               log.debug("Loaded config: "+configNames[n]);
+            }
+         }
+         else
+         {
+            throw new DeploymentException("Failed to find authConf as resource: "+authConf); 
+         }
+      }
+   }
+
+   /** Start the service. This entails unloading the AuthConf file contents
+    * using the LoginConfigService.
+    */
+   protected void stopService() throws Exception
+   {
+      MBeanServer server = super.getServer();
+      flushAuthenticationCaches();
+      if( configNames != null && configNames.length > 0 )
+      {
+         Object[] args = {configNames};
+         String[] sig = {configNames.getClass().getName()};
+         server.invoke(loginConfigService, "removeConfigs", args, sig);
+      }
+   }
+   
+   /**
+    * Ensure that the AuthConfig resource is not defaulting to
+    * the default login-config in the conf directory
+    * @param url
+    * @throws Exception
+    */
+   private void validateAuthConfigURL(String url) throws Exception
+   {
+      String msg = "AuthConfig is defaulting to conf/login-config.xml. " +
+            "Please check your archive.";
+      ServerConfigImplMBean mb = null;
+      try
+      {
+         mb = (ServerConfigImplMBean)MBeanProxy.get(ServerConfigImplMBean.class,
+               ServerConfigImplMBean.OBJECT_NAME, server);
+         URL serverConfigURL = mb.getServerConfigURL();
+         if(url.equalsIgnoreCase(serverConfigURL.toExternalForm() + "login-config.xml"))
+            throw new IllegalStateException(msg);
+      }
+      finally
+      {
+         //Clear the proxy
+         mb = null;
+      } 
+   }
+}

Added: trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfigMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfigMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/DynamicLoginConfigMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,88 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.login;
+
+import javax.management.ObjectName;
+
+import org.jboss.system.ServiceMBean;
+import org.jboss.security.config.PolicyConfig;
+
+/** The management interface for the DynamicLoginConfig service.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 45684 $
+ */
+public interface DynamicLoginConfigMBean
+   extends ServiceMBean
+{
+   /**
+    * Get the embedded PolicyConfig
+    * @return the PolicyConfig if it was specified, null otherwise.
+    */ 
+   public PolicyConfig getPolicyConfig();
+   /**
+    * Set the embedded PolicyConfig
+    * @param config - the embedded PolicyConfig object
+    */ 
+   public void setPolicyConfig(PolicyConfig config);
+
+   /** Get the resource path to the JAAS login configuration file to use.
+    */
+   public String getAuthConfig();
+   /** Set the resource path to the JAAS login configuration file to use.
+    * @param authConf - the classpath resource to load.
+    */
+   public void setAuthConfig(String authConf);
+
+   /** Get the XMLLoginConfig service to use for loading.
+    * @return the XMLLoginConfig service name.
+    */ 
+   public ObjectName getLoginConfigService();
+   /** Get the XMLLoginConfig service to use for loading. This service must
+    * support a String[] loadConfig(URL) operation to load the configurations. 
+    * 
+    * @param serviceName - the XMLLoginConfig service name.
+    */ 
+   public void setLoginConfigService(ObjectName serviceName);
+
+   /** Flush the caches of the security domains that have been registered
+    * by this service.
+    * @throws Exception
+    */ 
+   public void flushAuthenticationCaches() throws Exception;
+
+   /** Get the SecurityManagerService used to flush the registered security
+    * domains.
+    * @return the SecurityManagerService service name.
+    */
+   public ObjectName getSecurityManagerService();
+
+   /** Set the SecurityManagerService used to flush the registered security
+    * domains. This service must support an flushAuthenticationCache(String)
+    * operation to flush the case for the argument security domain. Setting
+    * this triggers the flush of the authentication caches when the service
+    * is stopped.
+    * @param serviceName - the SecurityManagerService service name.
+    */
+   public void setSecurityManagerService(ObjectName serviceName);
+
+}

Added: trunk/security/src/main/org/jboss/security/auth/login/SunConfigParser.jj
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/SunConfigParser.jj	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/SunConfigParser.jj	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,265 @@
+/* JBoss, the OpenSource J2EE WebOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+options {
+   LOOKAHEAD=1;
+   DEBUG_PARSER=true;
+   DEBUG_LOOKAHEAD=true;
+   DEBUG_TOKEN_MANAGER=false;
+}
+
+PARSER_BEGIN(SunConfigParser)
+
+package org.jboss.security.auth.login;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+/**
+ * A JavaCC 2.1 grammar for the default JAAS configuration file provided by Sun.
+ * The format of an entry is:
+ Application {
+	      ModuleClass  Flag    ModuleOptions;
+	      ModuleClass  Flag    ModuleOptions;
+	      ModuleClass  Flag    ModuleOptions;
+      };
+
+ * @see http://www.webgain.com/products/metamata/java_doc.html
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 16662 $
+ */
+public class SunConfigParser
+{
+   private XMLLoginConfigImpl loginConfig;
+
+   public SunConfigParser()
+   {
+      // keep the parser from feaking out, init using one of
+      // the JavaCC generated constructor
+      this(new StringReader(""));
+   }
+
+   public void parse(Reader configFile, XMLLoginConfigImpl loginConfig)
+      throws ParseException
+   {
+      parse(configFile, loginConfig, false);
+   }
+
+   public void parse(Reader configFile, XMLLoginConfigImpl loginConfig, boolean trace)
+      throws ParseException
+   {
+      ReInit(configFile);
+
+      // This will have no effect unless the debugging options are true
+      if (trace)
+      {
+         this.enable_tracing();
+      }
+      else
+      {
+         this.disable_tracing();
+      }
+
+      this.loginConfig = loginConfig;
+      this.config();
+   }
+
+   /**
+    * Strip off the leading and trailing (quote) chars from the given string
+    * and return it.  Does not actually check to make sure they are '\'' chars.
+    */
+   private String stripQuotes(String image)
+   {
+      return image.substring(1, image.length() - 1);
+   }
+
+   public static void doParse(Reader configFile, XMLLoginConfigImpl loginConfig)
+      throws ParseException
+   {
+      doParse(configFile, loginConfig, false);
+   }
+
+   public static void doParse(Reader configFile, XMLLoginConfigImpl loginConfig, boolean trace)
+      throws ParseException
+   {
+      SunConfigParser parser = new SunConfigParser();
+      parser.parse(configFile, loginConfig, trace);
+   }
+}
+
+PARSER_END(SunConfigParser)
+
+/* IGNORE WHITESPACE */
+
+SKIP :
+{
+    " "
+  | "\r"
+  | "\t"
+  | "\n"
+}
+
+
+SPECIAL_TOKEN : /* COMMENTS */
+{
+  <SINGLE_LINE_COMMENT: ("//"|"#") (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
+| <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
+}
+
+TOKEN :
+{
+  < OPEN_BKT:    "{" >
+  | < CLOSE_BKT:    "}" >
+  | < SEMI_COLON: ";" >
+  | < EQUALS:    "=" >
+
+}
+
+/* Literals */
+
+TOKEN :
+{
+    < LONG: ( ["0" - "9"] )+ >
+  | < DOUBLE: <FLOAT>
+	    | <FLOAT> ( ["e","E"] ([ "-","+"])? <LONG> )?
+    >
+  | < #FLOAT: <LONG> ( "." (<LONG>)? )
+	    | "." <LONG>
+    >
+  | < STRING:
+      (
+         "'"
+         (   (~["'","\n","\r"])
+           | ("''")
+         )*
+         "'"
+      )
+      |
+      (
+         "\""
+         (   (~["\"","\n","\r"])
+           | ("\"\"")
+         )*
+         "\""
+      ) >
+}
+
+TOKEN [IGNORE_CASE]:
+{
+  <CONTROL_FLAG: "required" | "requisite" | "sufficient" | "optional">
+|
+  <IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|"-"|"_")* >
+|
+  <CLASSNAME: <LETTER> (<LETTER>|<DIGIT>)* ("." <LETTER> (<LETTER>|<DIGIT>)*)* >
+|
+  <#LETTER: [ "_","$", "a"-"z", "A"-"Z" ] >
+|
+  <#DIGIT: ["0" - "9"] >
+|
+  <ANY: (<NOTSPACE_EQUALS>)+ >
+|
+  <#NOTSPACE_EQUALS: (~[" ","\t","\n","\r","=",";"]) >
+}
+
+/** Start of the grammar */
+
+void config() :
+{
+}
+{
+   ( appConfig() )* <EOF>
+}
+
+void appConfig() :
+{
+   Token t = null;
+   String appName;
+   AppConfigurationEntry entry;
+   ArrayList entries = new ArrayList();
+}
+{
+   t=<IDENTIFIER> { appName = t.image; } <OPEN_BKT>
+   (
+      entry = loginModuleConfig()
+      {
+         entries.add(entry);
+      }
+   ) +
+   <CLOSE_BKT> <SEMI_COLON>
+   {
+      AppConfigurationEntry[] appConfig = new AppConfigurationEntry[entries.size()];
+      entries.toArray(appConfig);
+      loginConfig.addAppConfig(appName, appConfig);
+   }
+}
+
+AppConfigurationEntry loginModuleConfig() :
+{
+   Token t = null;
+   String loginModuleClassName;
+   HashMap options = new HashMap();
+   LoginModuleControlFlag controlFlag;
+   AppConfigurationEntry entry;
+}
+{
+   t=<CLASSNAME> { loginModuleClassName = t.image; }
+      controlFlag = controlFlag()
+      ( moduleOptions(options) )*
+      <SEMI_COLON>
+      {
+         entry = new AppConfigurationEntry(loginModuleClassName, controlFlag, options);
+         return entry;
+      }
+}
+
+LoginModuleControlFlag controlFlag() :
+{
+   Token t;
+   LoginModuleControlFlag flag = null;
+}
+{
+   t=<CONTROL_FLAG>
+   {
+      if( LoginModuleControlFlag.REQUIRED.toString().indexOf(t.image) > 0 )
+         flag = LoginModuleControlFlag.REQUIRED;
+      else if( LoginModuleControlFlag.REQUISITE.toString().indexOf(t.image) > 0 )
+         flag = LoginModuleControlFlag.REQUISITE;
+      else if( LoginModuleControlFlag.SUFFICIENT.toString().indexOf(t.image) > 0 )
+         flag = LoginModuleControlFlag.SUFFICIENT;
+      else if( LoginModuleControlFlag.OPTIONAL.toString().indexOf(t.image) > 0 )
+         flag = LoginModuleControlFlag.OPTIONAL;
+      return flag;
+   }
+}
+
+void moduleOptions(HashMap options) :
+{
+   Token t;
+   String name, value;
+}
+{
+   ( t=<IDENTIFIER> | t=<CLASSNAME> )
+   { name = t.image; }
+   <EQUALS>
+   (
+      ( t=<IDENTIFIER> | t=<CLASSNAME> | t=<DOUBLE> | t=<LONG> | t=<ANY> )
+      {
+         value = t.image;
+         options.put(name, value);
+      }
+      | t=<STRING>
+      {
+         value = stripQuotes(t.image);
+         options.put(name, value);
+      }
+   )
+}
+

Added: trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfig.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfig.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfig.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,198 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.login;
+ 
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.io.IOException;
+import java.net.URL;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.AppConfigurationEntry;
+
+import org.jboss.security.config.ApplicationPolicy; 
+import org.jboss.system.ServiceMBeanSupport;
+
+/** An MBean for managing a XMLLoginConfigImpl instance.
+
+ @author Scott.Stark at jboss.org
+ @author Anil.Saldhana at jboss.org
+ @version $Revision: 56406 $
+ */
+public class XMLLoginConfig extends ServiceMBeanSupport
+      implements XMLLoginConfigMBean
+{
+   XMLLoginConfigImpl config; 
+
+   public XMLLoginConfig()
+   {
+      config = new XMLLoginConfigImpl();
+   }
+
+// --- Begin XMLLoginConfigMBean interface methods
+
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public URL getConfigURL()
+   {
+      return config.getConfigURL();
+   }
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public void setConfigURL(URL configURL)
+   {
+      config.setConfigURL(configURL);
+   }
+
+   /** Set the resource name of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public void setConfigResource(String resourceName)
+      throws IOException
+   {
+      config.setConfigResource(resourceName);
+   }
+
+   /** Get whether the login config xml document is validated againsts its DTD
+    */
+   public boolean getValidateDTD()
+   {
+      return config.getValidateDTD();
+   }
+   /** Set whether the login config xml document is validated againsts its DTD
+    */
+   public void setValidateDTD(boolean flag)
+   {
+      config.setValidateDTD(flag);
+   }
+
+   /**
+    * Add an application policy given a security domain name
+    */
+   public void addApplicationPolicy(String appName, ApplicationPolicy aPolicy)
+   {
+      config.addApplicationPolicy(appName,aPolicy); 
+   }
+   
+   /** Add an application login configuration. Any existing configuration for
+    the given appName will be replaced.
+    @deprecated
+    */
+   public void addAppConfig(String appName, AppConfigurationEntry[] entries)
+   {
+      config.addAppConfig(appName, entries);
+   }
+   
+   /** Remove an application login configuration.
+    */
+   public void removeAppConfig(String appName)
+   {
+      config.removeAppConfig(appName);
+   }
+
+   /**
+    * @see XMLLoginConfigMBean#getApplicationPolicy(String)
+    */
+   public ApplicationPolicy getApplicationPolicy(String domainName)
+   {
+      return (ApplicationPolicy)config.getApplicationPolicy(domainName); 
+   }
+   
+   /** Get the XML based configuration given the Configuration it should
+    delegate to when an application cannot be found.
+    */
+   public Configuration getConfiguration(Configuration prevConfig)
+   {
+      config.setParentConfig(prevConfig);
+      return config;
+   }
+
+   /** Load the login configuration information from the given config URL.
+    * @param configURL A URL to an XML or Sun login config file.
+    * @throws Exception on failure to load the configuration
+    */ 
+   public String[] loadConfig(URL configURL) throws Exception
+   {
+      return config.loadConfig(configURL);
+   }
+
+   public void removeConfigs(String[] appNames)
+   {
+      int count = appNames == null ? 0 : appNames.length;
+      for(int a = 0; a < count; a ++)
+         removeAppConfig(appNames[a]);
+   }
+
+   /** Display the login configuration for the given application.
+    */
+   public String displayAppConfig(String appName)
+   {
+      StringBuffer buffer = new StringBuffer("<h2>"+appName+" LoginConfiguration</h2>\n");
+      AppConfigurationEntry[] appEntry = config.getAppConfigurationEntry(appName);
+      if( appEntry == null )
+         buffer.append("No Entry\n");
+      else
+      {
+         for(int c = 0; c < appEntry.length; c ++)
+         {
+            AppConfigurationEntry entry = appEntry[c];
+            buffer.append("LoginModule Class: "+entry.getLoginModuleName());
+            buffer.append("\n<br>ControlFlag: "+entry.getControlFlag());
+            buffer.append("\n<br>Options:<ul>");
+            Map options = entry.getOptions();
+            Iterator iter = options.entrySet().iterator();
+            while( iter.hasNext() )
+            {
+               Entry e = (Entry) iter.next();
+               buffer.append("<li>");
+               buffer.append("name="+e.getKey());
+               buffer.append(", value="+e.getValue());
+               buffer.append("</li>\n");
+            }
+            buffer.append("</ul>\n");
+         }
+      }
+      return buffer.toString();
+   }
+// --- End XMLLoginConfigMBean interface methods
+
+// --- Begin ServiceMBeanSupport overriden methods
+
+   /** Load the configuration
+    */
+   protected void startService() throws Exception
+   {
+      config.loadConfig();
+   }
+
+   /** Clear all configuration entries
+    */
+   protected void destroyService()
+   {
+      config.clear();
+   }
+
+// --- End ServiceMBeanSupport overriden methods
+
+}

Added: trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigImpl.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigImpl.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigImpl.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,419 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.login;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Set;
+
+import javax.security.auth.AuthPermission;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.auth.spi.UsersObjectModelFactory; 
+import org.jboss.security.authorization.config.SecurityConfigObjectModelFactory;
+import org.jboss.security.config.ApplicationPolicy;
+import org.jboss.security.config.ApplicationPolicyRegistration;
+import org.jboss.security.config.PolicyConfig;
+import org.jboss.security.config.SecurityConfiguration;
+import org.jboss.xb.binding.JBossXBException;
+import org.jboss.xb.binding.Unmarshaller;
+import org.jboss.xb.binding.UnmarshallerFactory;
+
+/** An concrete implementation of the javax.security.auth.login.Configuration
+ class that parses an xml configuration of the form:
+
+ <policy>
+ <application-policy name = "test-domain">
+ <authentication>
+ <login-module code = "org.jboss.security.plugins.samples.IdentityLoginModule"
+ flag = "required">
+ <module-option name = "principal">starksm</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+ </policy>
+
+ @see javax.security.auth.login.Configuration
+
+ @author Scott.Stark at jboss.org
+ @author Anil.Saldhana at jboss.org
+ @version $Revision: 57482 $
+ */
+public class XMLLoginConfigImpl extends Configuration implements Serializable, ApplicationPolicyRegistration
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -8965860493224188277L;
+   private static final String DEFAULT_APP_CONFIG_NAME = "other";
+   private static final AuthPermission REFRESH_PERM = new AuthPermission("refreshLoginConfiguration");
+   private static Logger log = Logger.getLogger(XMLLoginConfigImpl.class);
+   /** A mapping of application name to AppConfigurationEntry[] 
+   protected Map appConfigs = Collections.synchronizedMap(new HashMap());
+   */
+   PolicyConfig appConfigs = new PolicyConfig();
+   /** The URL to the XML or Sun login configuration */
+   protected URL loginConfigURL;
+   /** The inherited configuration we delegate to */
+   protected Configuration parentConfig;
+   /** A flag indicating if XML configs should be validated */
+   private boolean validateDTD = true;
+
+   // --- Begin Configuration method overrrides
+   public void refresh()
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM);
+      if (log.isTraceEnabled())
+         log.trace("Begin refresh");      
+      appConfigs.clear();
+      loadConfig();
+      if (log.isTraceEnabled())
+         log.trace("End refresh");      
+   }
+
+   public AppConfigurationEntry[] getAppConfigurationEntry(String appName)
+   {
+      if (log.isTraceEnabled())
+         log.trace("Begin getAppConfigurationEntry("+appName+"), size="+appConfigs.size()); 
+      
+      //Load the config if PolicyConfig is empty
+      if(this.appConfigs.size() == 0)
+         this.loadConfig();
+
+      AppConfigurationEntry[] entry = null;
+      ApplicationPolicy aPolicy = this.getApplicationPolicy(appName); 
+      AuthenticationInfo authInfo = aPolicy != null ? (AuthenticationInfo)aPolicy.getAuthenticationInfo()
+                                     : null;
+       
+      if (authInfo == null)
+      {
+         if (log.isTraceEnabled())
+            log.trace("getAppConfigurationEntry("+appName+"), no entry in appConfigs, tyring parentCont: "+parentConfig);
+         if (parentConfig != null)
+            entry = parentConfig.getAppConfigurationEntry(appName);
+         if (entry == null)
+         {
+            if (log.isTraceEnabled())
+               log.trace("getAppConfigurationEntry("+appName+"), no entry in parentConfig, trying: "+DEFAULT_APP_CONFIG_NAME);
+         }
+         ApplicationPolicy defPolicy = (ApplicationPolicy)appConfigs.get(DEFAULT_APP_CONFIG_NAME);
+         authInfo = defPolicy != null ?(AuthenticationInfo) defPolicy.getAuthenticationInfo() : null;
+      }
+
+      if (authInfo != null)
+      {
+         if (log.isTraceEnabled())
+            log.trace("End getAppConfigurationEntry("+appName+"), authInfo=" + authInfo);
+         // Make a copy of the authInfo object
+         final AuthenticationInfo theAuthInfo = authInfo;
+         PrivilegedAction action = new PrivilegedAction()
+         {
+            public Object run()
+            {
+               return theAuthInfo.copyAppConfigurationEntry();
+            }
+         };
+         entry = (AppConfigurationEntry[]) AccessController.doPrivileged(action);
+      }
+      else
+      {
+         if (log.isTraceEnabled())
+            log.trace("End getAppConfigurationEntry("+appName+"), failed to find entry");
+      }
+
+      return entry;
+   }
+   // --- End Configuration method overrrides
+
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public URL getConfigURL()
+   {
+      return loginConfigURL;
+   }
+
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public void setConfigURL(URL loginConfigURL)
+   {
+      this.loginConfigURL = loginConfigURL;
+   }
+
+   public void setConfigResource(String resourceName)
+      throws IOException
+   {
+      ClassLoader tcl = Thread.currentThread().getContextClassLoader();
+      loginConfigURL = tcl.getResource(resourceName);
+      if (loginConfigURL == null)
+         throw new IOException("Failed to find resource: " + resourceName);
+   }
+
+   public void setParentConfig(Configuration parentConfig)
+   {
+      this.parentConfig = parentConfig;
+   }
+
+   /** Get whether the login config xml document is validated againsts its DTD
+    */
+   public boolean getValidateDTD()
+   {
+      return this.validateDTD;
+   }
+
+   /** Set whether the login config xml document is validated againsts its DTD
+    */
+   public void setValidateDTD(boolean flag)
+   {
+      this.validateDTD = flag;
+   }
+   
+   /**
+    * @see ApplicationPolicyRegistration#addApplicationPolicy(String, ApplicationPolicy)
+    */
+   public void addApplicationPolicy(String appName, ApplicationPolicy aPolicy)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM); 
+      appConfigs.add(aPolicy);
+      SecurityConfiguration.addApplicationPolicy(aPolicy);
+   }
+
+   /** Add an application configuration
+    */
+   public void addAppConfig(String appName, AppConfigurationEntry[] entries)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM); 
+      AuthenticationInfo authInfo = new AuthenticationInfo(appName);
+      authInfo.setAppConfigurationEntry(entries);
+      if (log.isTraceEnabled())
+         log.trace("addAppConfig("+appName+"), authInfo=" + authInfo); 
+      ApplicationPolicy aPolicy = new ApplicationPolicy(appName, authInfo);
+      appConfigs.add(aPolicy);
+      SecurityConfiguration.addApplicationPolicy(aPolicy);
+   }
+
+   /**
+    * @deprecated 
+    * @see #removeApplicationPolicy(String)
+    * @param appName
+    */
+   public void removeAppConfig(String appName)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM);
+      if (log.isTraceEnabled())
+         log.trace("removeAppConfig, appName="+appName);      
+      appConfigs.remove(appName);
+   }
+   
+   
+   /**
+    * @see ApplicationPolicyRegistration#getApplicationPolicy(String)
+    */
+   public ApplicationPolicy getApplicationPolicy(String domainName)
+   {
+      if(appConfigs == null || appConfigs.size() == 0)
+         loadConfig();
+      ApplicationPolicy aPolicy = (ApplicationPolicy)appConfigs.get(domainName);
+      if(aPolicy != null)
+         SecurityConfiguration.addApplicationPolicy(aPolicy);
+      return aPolicy;
+   } 
+
+   
+   /**
+    * @see ApplicationPolicyRegistration#removeApplicationPolicy(String)
+    */
+   public boolean removeApplicationPolicy(String appName)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM);
+      if (log.isTraceEnabled())
+         log.trace("removeAppConfig, appName="+appName);      
+      appConfigs.remove(appName);
+      return true;
+   }
+   
+   /**
+    * Method that returns the parsed AuthenticationInfo needed by
+    * the JASPI framework until a seperate Configuration mechanism
+    * for JASPI is established
+    * 
+    * @return the parsed AuthenticationInfo object
+    */
+   public BaseAuthenticationInfo getAuthenticationInfo(String domainName)
+   { 
+      ApplicationPolicy aPolicy = getApplicationPolicy( domainName);
+      return aPolicy != null ? aPolicy.getAuthenticationInfo() : null; 
+   }
+
+   public void clear()
+   {
+
+   }
+
+   /** Called to try to load the config from the java.security.auth.login.config
+    * property value when there is no loginConfigURL.
+    */
+   public void loadConfig()
+   {
+      // Try to load the java.security.auth.login.config property
+      String loginConfig = System.getProperty("java.security.auth.login.config");
+      if (loginConfig == null)
+         loginConfig = "login-config.xml";
+
+      // If there is no loginConfigURL build it from the loginConfig
+      if (loginConfigURL == null)
+      {
+         try
+         {
+            // Try as a URL
+            loginConfigURL = new URL(loginConfig);
+         }
+         catch (MalformedURLException e)
+         {
+            // Try as a resource
+            try
+            {
+               setConfigResource(loginConfig);
+            }
+            catch (IOException ignore)
+            {
+               // Try as a file
+               File configFile = new File(loginConfig);
+               try
+               {
+                  setConfigURL(configFile.toURL());
+               }
+               catch (MalformedURLException ignore2)
+               {
+               }
+            }
+         }
+      }
+
+      if (loginConfigURL == null)
+      {
+         log.warn("Failed to find config: " + loginConfig);
+         return;
+      }
+
+      if (log.isTraceEnabled())
+         log.trace("Begin loadConfig, loginConfigURL="+loginConfigURL);      
+      // Try to load the config if found
+      try
+      {
+         loadConfig(loginConfigURL);
+         if (log.isTraceEnabled())
+            log.trace("End loadConfig, loginConfigURL="+loginConfigURL);      
+      }
+      catch (Exception e)
+      {
+         e.printStackTrace();
+         log.warn("End loadConfig, failed to load config: " + loginConfigURL, e);
+      }
+   }
+
+   protected String[] loadConfig(URL config) throws Exception
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(REFRESH_PERM);
+
+      ArrayList configNames = new ArrayList();
+      log.debug("Try loading config as XML, url=" + config);
+      try
+      {
+         loadXMLConfig(config, configNames);
+      }
+      catch(Throwable e)
+      {
+         log.debug("Failed to load config as XML", e);
+         log.debug("Try loading config as Sun format, url=" + config);
+         loadSunConfig(config, configNames);
+      }
+      String[] names = new String[configNames.size()];
+      configNames.toArray(names);
+      return names;
+   }
+
+   private void loadSunConfig(URL sunConfig, ArrayList configNames)
+      throws Exception
+   {
+      InputStream is = sunConfig.openStream();
+      if (is == null)
+         throw new IOException("InputStream is null for: " + sunConfig);
+
+      InputStreamReader configFile = new InputStreamReader(is);
+      boolean trace = log.isTraceEnabled();
+      SunConfigParser.doParse(configFile, this, trace);
+   }
+
+   private void loadXMLConfig(URL loginConfigURL, ArrayList configNames)
+      throws IOException, JBossXBException
+   {
+      LoginConfigObjectModelFactory lcomf = new SecurityConfigObjectModelFactory();
+      UsersObjectModelFactory uomf = new UsersObjectModelFactory();
+
+      InputStreamReader xmlReader = loadURL(loginConfigURL);
+      Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
+      unmarshaller.mapFactoryToNamespace(uomf, "http://www.jboss.org/j2ee/schemas/XMLLoginModule");
+      Object root = null;
+      PolicyConfig config = (PolicyConfig) unmarshaller.unmarshal(xmlReader, lcomf, root);
+      Set<String> cnames = config.getConfigNames();
+      configNames.addAll(cnames);
+      appConfigs.copy(config);
+      //Add the config to SecurityConfiguration
+      for(String cname:cnames)
+      {
+         SecurityConfiguration.addApplicationPolicy(config.get(cname));
+      }
+   }
+
+   private InputStreamReader loadURL(URL configURL)
+      throws IOException
+   {
+      InputStream is = configURL.openStream();
+      if (is == null)
+         throw new IOException("Failed to obtain InputStream from url: " + configURL);
+      InputStreamReader xmlReader = new InputStreamReader(is);
+      return xmlReader;
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/login/XMLLoginConfigMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,112 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.login;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.management.ObjectName;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+
+import org.jboss.mx.util.ObjectNameFactory;
+import org.jboss.security.config.ApplicationPolicy;
+import org.jboss.system.ServiceMBean;
+
+/** The managment bean interface for the XML based JAAS login configuration
+ object.
+
+ at author  Scott.Stark at jboss.org
+ at version $Revision: 45984 $
+ */
+public interface XMLLoginConfigMBean extends ServiceMBean
+{
+   /** Default ObjectName
+    */
+   public static final ObjectName OBJECT_NAME = 
+      ObjectNameFactory.create("jboss.security:service=XMLLoginConfig");
+   
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public URL getConfigURL();
+   /** Set the URL of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public void setConfigURL(URL configURL);
+
+   /** Set the resource name of the XML login configuration file that should
+    be loaded by this mbean on startup.
+    */
+   public void setConfigResource(String resourceName) throws IOException;
+
+   /** Get whether the login config xml document is validated againsts its DTD
+    */
+   public boolean getValidateDTD();
+   /** Set whether the login config xml document is validated againsts its DTD
+    */
+   public void setValidateDTD(boolean flag);
+   
+   /**
+    * Get the Application Policy given the domain name
+    */
+   public ApplicationPolicy getApplicationPolicy(String domainName);
+
+   /** Get the XML based configuration given the Configuration it should
+    delegate to when an application cannot be found.
+    */
+   public Configuration getConfiguration(Configuration prevConfig);
+   
+   /**
+    * Add an Application Policy given a domain name to the configuration
+    * @param appName
+    * @param aPolicy
+    */
+   public void addApplicationPolicy(String appName, ApplicationPolicy aPolicy);
+
+   /** Add an application login configuration. Any existing configuration for
+    the given appName will be replaced.
+    @deprecated
+    */
+   public void addAppConfig(String appName, AppConfigurationEntry[] entries);
+   /** Remove an application login configuration.
+    */
+   public void removeAppConfig(String appName);
+
+   /** Load the login configuration information from the given config URL.
+    * @param configURL A URL to an XML or Sun login config file.
+    * @return An array of the application config names loaded
+    * @throws Exception on failure to load the configuration
+    */ 
+   public String[] loadConfig(URL configURL) throws Exception;
+   /** Remove the given login configurations. This invokes removeAppConfig
+    * for each element of appNames.
+    * 
+    * @param appNames the names of the login configurations to remove. 
+    */ 
+   public void removeConfigs(String[] appNames);
+
+   /** Display the login configuration for the given application.
+    */
+   public String displayAppConfig(String appName);
+}
+

Added: trunk/security/src/main/org/jboss/security/auth/spi/RFC2617Digest.java
===================================================================
--- trunk/security/src/main/org/jboss/security/auth/spi/RFC2617Digest.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/auth/spi/RFC2617Digest.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,397 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.auth.spi;
+
+import java.util.Map;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import javax.security.auth.callback.Callback;
+
+import org.jboss.crypto.digest.DigestCallback;
+import org.jboss.security.auth.callback.MapCallback;
+
+/**
+ An implementation of the DigestCallback that support the http digest auth as
+ described in RFC2617 (http://www.ietf.org/rfc/rfc2617.txt).
+
+ 3.2.2.1 Request-Digest
+
+ If the "qop" value is "auth" or "auth-int":
+
+ request-digest  = <"> < KD ( H(A1),     unq(nonce-value) ":" nc-value ":"
+ unq(cnonce-value) ":" unq(qop-value) ":" H(A2) ) <">
+
+ If the "qop" directive is not present (this construction is for compatibility
+ with RFC 2069):
+
+ request-digest  = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
+
+ See below for the definitions for A1 and A2.
+
+ 3.2.2.2 A1
+
+ If the "algorithm" directive's value is "MD5" or is unspecified, then A1 is:
+
+ A1       = unq(username-value) ":" unq(realm-value) ":" passwd
+
+ where
+
+ passwd   = < user's password >
+
+ If the "algorithm" directive's value is "MD5-sess", then A1 is calculated only
+ once - on the first request by the client following receipt of a
+ WWW-Authenticate challenge from the server.  It uses the server nonce from that
+ challenge, and the first client nonce value to construct A1 as follows:
+
+ A1       = H( unq(username-value) ":" unq(realm-value) ":" passwd ) ":"
+ unq(nonce-value) ":" unq(cnonce-value)
+
+ This creates a 'session key' for the authentication of subsequent requests and
+ responses which is different for each "authentication session", thus limiting
+ the amount of material hashed with any one key.  (Note: see further discussion
+ of the authentication session in section 3.3.) Because the server need only use
+ the hash of the user credentials in order to create the A1 value, this
+ construction could be used in conjunction with a third party authentication
+ service so that the web server would not need the actual password value.  The
+ specification of such a protocol is beyond the scope of this specification.
+
+ 3.2.2.3 A2
+
+ If the "qop" directive's value is "auth" or is unspecified, then A2 is:
+
+ A2       = Method ":" digest-uri-value
+
+ If the "qop" value is "auth-int", then A2 is:
+
+ A2       = Method ":" digest-uri-value ":" H(entity-body)
+
+ 3.2.2.4 Directive values and quoted-string
+
+ Note that the value of many of the directives, such as "username- value", are
+ defined as a "quoted-string". However, the "unq" notation indicates that
+ surrounding quotation marks are removed in forming the string A1. Thus if the
+ Authorization header includes the fields
+
+ username="Mufasa", realm=myhost at testrealm.com
+
+ and the user Mufasa has password "Circle Of Life" then H(A1) would be
+ H(Mufasa:myhost at testrealm.com:Circle Of Life) with no quotation marks in the
+ digested string.
+
+ No white space is allowed in any of the strings to which the digest function H()
+ is applied unless that white space exists in the quoted strings or entity body
+ whose contents make up the string to be digested. For example, the string A1
+ illustrated above must be
+
+ Mufasa:myhost at testrealm.com:Circle Of Life
+
+ with no white space on either side of the colons, but with the white space
+ between the words used in the password value.  Likewise, the other strings
+ digested by H() must not have white space on either side of the colons which
+ delimit their fields unless that white space was in the quoted strings or entity
+ body being digested.
+
+ Also note that if integrity protection is applied (qop=auth-int), the
+ H(entity-body) is the hash of the entity body, not the message body - it is
+ computed before any transfer encoding is applied by the sender and after it has
+ been removed by the recipient. Note that this includes multipart boundaries and
+ embedded headers in each part of any multipart content-type.
+
+ @author Scott.Stark at jboss.org
+ @version $Revision: 37459 $
+ */
+public class RFC2617Digest implements DigestCallback
+{
+   /**
+    String which can enable users to know which username and password to use, in
+    case they might have different ones for different servers.
+    */
+   public static final String REALM = "realm";
+   /**
+    The user's name in the specified realm.
+    */
+   public static final String USERNAME = "username";
+   /**
+    The URI from Request-URI of the Request-Line; duplicated here because proxies
+    are allowed to change the Request-Line in transit.
+    */
+   public static final String DIGEST_URI = "digest-uri";
+   /**
+    A server-specified data string which MUST be different each time a
+    digest-challenge is sent as part of initial authentication.  It is
+    recommended that this string be base64 or hexadecimal data. Note that since
+    the string is passed as a quoted string, the double-quote character is not
+    allowed unless escaped (see section 7.2). The contents of the nonce are
+    implementation dependent. The
+
+    security of the implementation depends on a good choice. It is RECOMMENDED
+    that it contain at least 64 bits of entropy. The nonce is opaque to the
+    client. This directive is required and MUST appear exactly once; if not
+    present, or if multiple instances are present, the client should abort the
+    authentication exchange.
+    */
+   public static final String NONCE = "nonce";
+   /**
+    This MUST be specified if a qop directive is sent (see above), and MUST NOT
+    be specified if the server did not send a qop directive in the
+    WWW-Authenticate header field.  The cnonce-value is an opaque quoted string
+    value provided by the client and used by both client and server to avoid
+    chosen plaintext attacks, to provide mutual authentication, and to provide
+    some message integrity protection. See the descriptions below of the
+    calculation of the response- digest and request-digest values.
+    */
+   public static final String CNONCE = "cnonce";
+   /**
+    This MUST be specified if a qop directive is sent (see above), and MUST NOT
+    be specified if the server did not send a qop directive in the
+    WWW-Authenticate header field.  The nc-value is the hexadecimal count of the
+    number of requests (including the current request) that the client has sent
+    with the nonce value in this request.  For example, in the first request sent
+    in response to a given nonce value, the client sends "nc=00000001".  The
+    purpose of this directive is to allow the server to detect request replays by
+    maintaining its own copy of this count - if the same nc-value is seen twice,
+    then the request is a replay.   See the description below of the construction
+    of the request-digest value.
+    */
+   public static final String NONCE_COUNT = "nc";
+   /**
+    Indicates what "quality of protection" the client has applied to the message.
+    If present, its value MUST be one of the alternatives the server indicated it
+    supports in the WWW-Authenticate header. These values affect the computation
+    of the request-digest. Note that this is a single token, not a quoted list of
+    alternatives as in WWW- Authenticate.  This directive is optional in order to
+    preserve backward compatibility with a minimal implementation of RFC 2069
+    [6], but SHOULD be used if the server indicated that qop is supported by
+    providing a qop directive in the WWW-Authenticate header field.
+    */
+   public static final String QOP = "qop";
+   /**
+    A string indicating a pair of algorithms used to produce the digest
+     and a checksum. If this is not present it is assumed to be "MD5".
+     If the algorithm is not understood, the challenge should be ignored
+     (and a different one used, if there is more than one).
+
+     In this document the string obtained by applying the digest
+     algorithm to the data "data" with secret "secret" will be denoted
+     by KD(secret, data), and the string obtained by applying the
+     checksum algorithm to the data "data" will be denoted H(data). The
+     notation unq(X) means the value of the quoted-string X without the
+     surrounding quotes.
+    */
+   public static final String ALGORITHM = "algorithm";
+   /**
+    This directive allows for future extensions. Any unrecognized directive MUST
+    be ignored.
+    */
+   public static final String AUTH_PARAM = "auth-param";
+   /**
+    The http method type
+    */
+   public static final String METHOD = "method";
+   /**
+    An explicit A2 digest
+    */
+   public static final String A2HASH = "a2hash";
+   /**
+    The ASCII printable characters the MD5 digest maps to
+    */
+   private static char[] MD5_HEX = "0123456789abcdef".toCharArray();
+
+   private MapCallback info;
+   private String username;
+   private String password;
+   private boolean passwordIsA1Hash;
+   String rfc2617;
+
+   public void init(Map options)
+   {
+      username = (String) options.get("javax.security.auth.login.name");
+      password = (String) options.get("javax.security.auth.login.password");
+      String flag = (String) options.get("passwordIsA1Hash");
+      if( flag != null )
+         passwordIsA1Hash = Boolean.valueOf(flag).booleanValue();
+
+      // Ask for MapCallback to obtain the digest parameters
+      info = new MapCallback();
+      Callback[] callbacks = {info};
+      options.put("callbacks", callbacks);
+   }
+
+   public void preDigest(MessageDigest digest)
+   {
+   }
+   public void postDigest(MessageDigest digest)
+   {
+      String qop = (String) info.getInfo(QOP);
+      String realm = (String) info.getInfo(REALM);
+      String algorithm = (String) info.getInfo(ALGORITHM);
+      String nonce = (String) info.getInfo(NONCE);
+      String cnonce = (String) info.getInfo(CNONCE);
+      String method = (String) info.getInfo(METHOD);
+      String nc = (String) info.getInfo(NONCE_COUNT);
+      String digestURI = (String) info.getInfo(DIGEST_URI);
+
+      if( algorithm == null )
+         algorithm = digest.getAlgorithm();
+      // This replaces the existing hash, it does not add to it
+      digest.reset();
+
+      String hA1 = null;
+      // 3.2.2.2 A1
+      if (algorithm == null || algorithm.equals("MD5"))
+      {
+         if( passwordIsA1Hash )
+            hA1 = password;
+         else
+         {
+            String A1 = username + ":" + realm + ":" + password;
+            hA1 = H(A1, digest);
+         }
+      }
+      else if (algorithm.equals("MD5-sess"))
+      {
+         if( passwordIsA1Hash )
+         {
+            hA1 = password + ":" + nonce + ":" + cnonce;
+         }
+         else
+         {
+            String A1 = username + ":" + realm + ":" + password;
+            hA1 = H(A1, digest) + ":" + nonce + ":" + cnonce;
+         }
+      }
+      else
+      {
+         throw new IllegalArgumentException("Unsupported algorigthm: "+algorithm);
+      }
+
+      // 3.2.2.3 A2. First check to see if the A2 hash has been precomputed
+      String hA2 = (String) info.getInfo(A2HASH);
+      if (hA2 == null)
+      {
+         // No, compute it based on qop
+         String A2 = null;
+         if (qop == null | qop.equals("auth"))
+         {
+            A2 = method + ":" + digestURI;
+         }
+         else
+         {
+            throw new IllegalArgumentException("Unsupported qop="+qop);
+         }
+         hA2 = H(A2, digest);
+      }
+
+      // 3.2.2.1 Request-Digest
+      if (qop == null)
+      {
+         String extra = nonce + ":" + hA2;
+         KD(hA1, extra, digest);
+      }
+      else if (qop.equals("auth"))
+      {
+         String extra = nonce +
+            ":" + nc +
+            ":" + cnonce +
+            ":" + qop +
+            ":" + hA2;
+         KD(hA1, extra, digest);
+      }
+   }
+
+   public String getInfoDigest(MessageDigest digest)
+   {
+      if( rfc2617 == null )
+      {
+         byte[] data = digest.digest();
+         rfc2617 = cvtHex(data);
+      }
+      return rfc2617;
+   }
+
+   static private String H(String data, MessageDigest digest)
+   {
+      digest.reset();
+      byte[] x = digest.digest(data.getBytes());
+      return cvtHex(x);
+   }
+   static private void KD(String secret, String data, MessageDigest digest)
+   {
+      String x = secret + ":" + data;
+      digest.reset();
+      digest.update(x.getBytes());
+   }
+
+   /**
+    3.1.3 Representation of digest values
+
+    An optional header allows the server to specify the algorithm used to create
+    the checksum or digest. By default the MD5 algorithm is used and that is the
+    only algorithm described in this document.
+
+    For the purposes of this document, an MD5 digest of 128 bits is represented
+    as 32 ASCII printable characters. The bits in the 128 bit digest are
+    converted from most significant to least significant bit, four bits at a time
+    to their ASCII presentation as follows. Each four bits is represented by its
+    familiar hexadecimal notation from the characters 0123456789abcdef. That is,
+    binary 0000 getInfos represented by the character '0', 0001, by '1', and so on up
+    to the representation of 1111 as 'f'.
+    
+    @param data - the raw MD5 hash data
+    @return the encoded MD5 representation
+    */
+   static String cvtHex(byte[] data)
+   {
+      char[] hash = new char[32];
+      for (int i = 0; i < 16; i++)
+      {
+         int j = (data[i] >> 4) & 0xf;
+         hash[i * 2] = MD5_HEX[j];
+         j = data[i] & 0xf;
+         hash[i * 2 + 1] = MD5_HEX[j];
+      }
+      return new String(hash);
+   }
+
+   /**
+    Compute the 
+    @param args
+    */
+   public static void main(String[] args) throws NoSuchAlgorithmException
+   {
+      if( args.length != 3 )
+      {
+         System.err.println("Usage: RFC2617Digest username realm password");
+         System.err.println(" - username : the username");
+         System.err.println(" - realm : the web app realm name");
+         System.err.println(" - password : the plain text password");
+         System.exit(1);
+      }
+      String username = args[0];
+      String realm = args[1];
+      String password = args[2];
+      String A1 = username + ":" + realm + ":" + password;
+      MessageDigest digest = MessageDigest.getInstance("MD5");
+      String hA1 = H(A1, digest);
+      System.out.println("RFC2617 A1 hash: "+hA1);
+   }
+}

Added: trunk/security/src/main/org/jboss/security/jce/JCEProviderService.java
===================================================================
--- trunk/security/src/main/org/jboss/security/jce/JCEProviderService.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/jce/JCEProviderService.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,228 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.jce;
+
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.jboss.system.ServiceMBeanSupport;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * The JCEProviderService is capable of loading one or more third party 
+ * JCE providers at runtime. The configuration looks something like:<br>
+ * <pre>
+ *  &lt;mbean code="org.jboss.security.jce.JCEProviderService"
+ *     name="Security:service=JCEProviderService"&gt;
+ *     &lt;attribute name="JceProviders"&gt;
+ *        &lt;providers&gt;
+ *           &lt;provider class="org.bouncycastle.jce.provider.BouncyCastleProvider" position="3"/&gt;
+ *           &lt;provider class="cryptix.provider.Cryptix"/&gt;
+ *        &lt;/providers&gt;
+ *     &lt;/attribute&gt;
+ *  &lt;/mbean&gt;
+ * </pre>
+ * The required class attribute is the class name of the Provider to load. The optional position attribute
+ * is the position in the provider list that this provider would like to be loaded.<p>
+ * Any provider that already exists in the provider list will not be loaded again, and it will not be removed from
+ * the list when the JCEProviderService is destroyed.
+ * 
+ * @author <a href="mailto:jasone at greenrivercomputing.com">Jason Essington</a>
+ * @version $Revision: 37459 $
+ */
+public class JCEProviderService extends ServiceMBeanSupport implements JCEProviderServiceMBean
+{
+   private ArrayList addedProviders = new ArrayList();
+   private Element providers;
+
+   public void setJceProviders(Element element)
+   {
+      providers = element;
+      if (getState() != UNREGISTERED)
+      {
+         synchronized (JCEProviderService.class)
+         {
+            removeProviders();
+            loadProviders();
+         }
+      }
+   }
+
+   public Element getJceProviders()
+   {
+      return providers;
+   }
+
+   protected void createService() throws Exception
+   {
+      // Install the requested JCE providers
+      synchronized (JCEProviderService.class)
+      {
+         loadProviders();
+      }
+   }
+
+   protected void destroyService()
+   {
+      // Uninstall any JCE Providers that we actually loaded
+      synchronized (JCEProviderService.class)
+      {
+         removeProviders();
+      }
+   }
+
+   private void loadProviders()
+   {
+      int n = 0;
+      if (providers != null)
+      {
+         addedProviders = new ArrayList();
+         NodeList reqdProviders = providers.getElementsByTagName("provider");
+         n = reqdProviders.getLength();
+         //int providersLoaded = 0;
+
+         for (int i = 0; i < n; i++)
+         {
+            Provider provider;
+            Node reqdProvider = reqdProviders.item(i);
+
+            String providerName;
+            String providerClass;
+            int requestedPosition = 0;
+
+            if (Node.ELEMENT_NODE == reqdProvider.getNodeType())
+            {
+               Element prov = (Element) reqdProvider;
+               if (prov.hasAttribute("class"))
+               {
+                  providerClass = prov.getAttribute("class");
+               }
+               else
+               {
+                  log.warn("A provider element must, at the very least, have a class attribute: " + prov);
+                  continue;
+               }
+
+               try
+               {
+                  provider = (Provider) Class.forName(providerClass).newInstance();
+               }
+               catch (InstantiationException e1)
+               {
+                  log.warn("Unable to instantiate an instance of the JCE Provider class " + providerClass, e1);
+                  continue;
+               }
+               catch (IllegalAccessException e1)
+               {
+                  log.warn("No permission to access the JCE Provider class " + providerClass, e1);
+                  continue;
+               }
+               catch (ClassNotFoundException e1)
+               {
+                  log.warn("Could not find the JCE Provider class " + providerClass, e1);
+                  continue;
+               }
+               catch (ClassCastException e1)
+               {
+                  log.warn("The Class " + providerClass + " is not a java.security.Provider");
+                  continue;
+               }
+
+               providerName = provider.getName();
+
+               if (prov.hasAttribute("position"))
+               {
+                  try
+                  {
+                     requestedPosition = Integer.parseInt(prov.getAttribute("position"));
+                  }
+                  catch (NumberFormatException e)
+                  {
+                     log.warn("the position '" + prov.getAttribute("position")
+                           + "' is not a valid number. This provider has to go to the end of the line. " + prov);
+                  }
+               }
+
+               int pos;
+               if (requestedPosition < 1)
+               {
+                  pos = Security.addProvider(provider);
+               }
+               else
+               {
+                  pos = Security.insertProviderAt(provider, requestedPosition);
+               }
+
+               if (pos == -1)
+               {
+                  int exPos = Arrays.asList(Security.getProviders()).indexOf(provider);
+                  log.info("The provider " + providerName + " already exists at position " + exPos);
+               }
+               else if (requestedPosition >= 1 && pos != requestedPosition)
+               {
+                  log.info("The position " + requestedPosition + " was requested for Provider " + providerName
+                        + " but it was added at position " + pos);
+                  addedProviders.add(providerName);
+               }
+               else
+               {
+                  log.info("The Provider " + providerName + " was added at position " + pos);
+                  addedProviders.add(providerName);
+               }
+            }
+            else
+            {
+               if (log.isDebugEnabled())
+                  log.debug("Ignoring node" + reqdProvider);
+            }
+         }
+
+         if (addedProviders.size() == 1)
+            log.info(addedProviders.size() + " JCE Provider was actually loaded.");
+         else
+            log.info(addedProviders.size() + " JCE Providers were actually loaded.");
+
+      }
+      if (n < 1)
+         log.info("No JCE Providers were requested.");
+   }
+   private void removeProviders()
+   {
+      for (Iterator iter = addedProviders.iterator(); iter.hasNext();)
+      {
+         String providerName = (String) iter.next();
+         try
+         {
+            Security.removeProvider(providerName);
+         }
+         catch (Exception e)
+         {
+            log.warn("Failed to remove Provider " + providerName);
+         }
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/jce/JCEProviderServiceMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/jce/JCEProviderServiceMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/jce/JCEProviderServiceMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,35 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.jce;
+
+import org.jboss.system.ServiceMBean;
+import org.w3c.dom.Element;
+
+/**
+ * @author <a href="mailto:jasone at greenrivercomputing.com">Jason Essington</a>
+ * @version $Revision: 37459 $
+ */
+public interface JCEProviderServiceMBean extends ServiceMBean
+{
+   public void setJceProviders(Element element);
+   public Element getJceProviders();
+}

Added: trunk/security/src/main/org/jboss/security/jndi/JndiLoginInitialContextFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/jndi/JndiLoginInitialContextFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/jndi/JndiLoginInitialContextFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,160 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.jndi;
+
+import org.jboss.naming.NamingContextFactory;
+import org.jboss.security.SimplePrincipal;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.Principal;
+import java.util.Hashtable;
+
+/** A naming provider InitialContextFactory implementation that combines the
+ * authentication phase with the InitialContext creation. During the
+ * getInitialContext callback from the JNDI naming, layer security context
+ * identity is populated with the username obtained from the
+ * Context.SECURITY_PRINCIPAL env property and the credentials from the
+ * Context.SECURITY_CREDENTIALS env property. There is no actual authentication
+ * of this information. It is merely made available to the jboss transport
+ * layer for incorporation into subsequent invocations. Authentication and
+ * authorization will occur on the server.
+ *
+ * @see javax.naming.spi.InitialContextFactory
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public class JndiLoginInitialContextFactory extends NamingContextFactory
+{
+   // InitialContextFactory implementation --------------------------
+
+   /** Take the env Context.SECURITY_PRINCIPAL and Context.SECURITY_CREDENTIALS
+    * and propagate these to the SecurityAssociation principal and credential.
+    * If Context.SECURITY_PRINCIPAL is a java.security.Principal then it is
+    * used as is, otherwise its treated as a name using toString and a
+    * SimplePrincipal is created. The Context.SECURITY_CREDENTIALS is passed
+    * as is.
+    * @param env
+    * @throws NamingException
+    */
+   public Context getInitialContext(Hashtable env)
+      throws NamingException
+   {
+      // Get the login principal and credentials from the JNDI env
+      Object credentials = env.get(Context.SECURITY_CREDENTIALS);
+      Object principal = env.get(Context.SECURITY_PRINCIPAL);
+      Principal securityPrincipal = null;
+      /** Flag indicating if the SecurityAssociation existing at login should
+      be restored on logout.
+      */
+      String flag = (String) env.get("jnp.multi-threaded");
+      if (Boolean.valueOf(flag).booleanValue() == true)
+      {
+         /* Turn on the server mode which uses thread local storage for
+            the principal information.
+         */
+         SecurityAssociationActions.setServer();
+      }
+      boolean restoreLoginIdentity = false;
+      flag = (String) env.get("jnp.restoreLoginIdentity");
+      if( flag != null )
+         restoreLoginIdentity = Boolean.parseBoolean(flag);
+      // See if the principal is a Principal or String
+      if( principal instanceof Principal )
+      {
+         securityPrincipal = (Principal) principal; 
+      }
+      else
+      {
+         // Simply convert this to a name using toString
+         String username = principal.toString();
+         securityPrincipal = new SimplePrincipal(username);
+      }
+      // Associate this security context
+      if( restoreLoginIdentity )
+      {
+         SecurityAssociationActions.setPrincipalInfo(securityPrincipal, credentials, null);
+      }
+      else
+      {
+         SecurityAssociationActions.setPrincipalInfo(securityPrincipal, credentials);
+      }
+      // Now return the context using the standard jnp naming context factory
+      Context iniCtx = super.getInitialContext(env);
+      if( restoreLoginIdentity )
+      {
+         // Use a proxy to pop the stack when the context is closed
+         ClassLoader loader = SecurityAssociationActions.getContextClassLoader();
+         ContextProxy handler = new ContextProxy(iniCtx);
+         Class[] ifaces = {Context.class};
+         iniCtx = (Context) Proxy.newProxyInstance(loader, ifaces, handler);
+      }
+      return iniCtx;
+   }
+
+   /**
+    * 
+    */
+   public static class ContextProxy implements InvocationHandler
+   {
+      private Context delegate;
+      ContextProxy(Context delegate)
+      {
+         this.delegate = delegate;
+      }
+      public Object invoke(Object proxy, Method method, Object[] args)
+         throws Throwable
+      {
+         boolean close = false;
+         try
+         {
+            close = method.getName().equals("close");
+            return method.invoke(delegate, args);
+         }
+         catch(InvocationTargetException e)
+         {
+            throw e.getTargetException();
+         }
+         finally
+         {
+            if( close )
+            {
+               // Pop the security context on close
+               try
+               {
+                  SecurityAssociationActions.popPrincipalInfo();
+               }
+               catch(Throwable ignore)
+               {
+               }
+            }
+         }
+      }
+      
+   }
+}

Added: trunk/security/src/main/org/jboss/security/jndi/LoginInitialContextFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/jndi/LoginInitialContextFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/jndi/LoginInitialContextFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,99 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.jndi;
+
+import java.util.Hashtable;
+import java.security.Principal;
+import javax.naming.AuthenticationException;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.jnp.interfaces.NamingContextFactory;
+import org.jboss.security.auth.callback.UsernamePasswordHandler;
+
+/** A naming provider InitialContextFactory implementation that combines the authentication phase
+ * with the InitialContext creation. During the getInitialContext callback from the JNDI naming
+ * layer a JAAS LoginContext is created using the login configuration name passed in as
+ * the Context.SECURITY_PROTOCOL env property. The CallbackHandler used is a
+ * org.jboss.security.auth.callback.UsernamePasswordHandler that is populated
+ * with the username obtained from the Context.SECURITY_PRINCIPAL env property
+ * and the credentials from the Context.SECURITY_CREDENTIALS env property.
+ *
+ * @see javax.naming.spi.InitialContextFactory
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public class LoginInitialContextFactory extends NamingContextFactory
+{
+   // InitialContextFactory implementation --------------------------
+
+   /** Create new initial context by invoking the NamingContextFactory version of this
+    * method after performing a JAAS login.
+    *
+    */
+   public Context getInitialContext(Hashtable env)
+      throws NamingException
+   {
+      // Get the login configuration name to use, defaulting to "other"
+      String protocol = "other";
+      Object prop = env.get(Context.SECURITY_PROTOCOL);
+      if( prop != null )
+         protocol = prop.toString();
+
+      // Get the login principal and credentials from the JNDI env
+      Object credentials = env.get(Context.SECURITY_CREDENTIALS);
+      Object principal = env.get(Context.SECURITY_PRINCIPAL);
+      try
+      {
+         // Get the principal username
+         String username;
+         if( principal instanceof Principal )
+         {
+            Principal p = (Principal) principal;
+            username = p.getName();
+         }
+         else
+         {
+            username = principal.toString();
+         }
+         UsernamePasswordHandler handler = new UsernamePasswordHandler(username,
+            credentials);
+         // Do the JAAS login
+         LoginContext lc = new LoginContext(protocol, handler);
+         lc.login();
+      }
+      catch(LoginException e)
+      {
+         AuthenticationException ex = new AuthenticationException("Failed to login using protocol="+protocol);
+         ex.setRootCause(e);
+         throw ex;
+      }
+
+      // Now return the context using the standard jnp naming context factory
+      Context iniCtx = super.getInitialContext(env);
+      return iniCtx;
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/jndi/SecurityAssociationActions.java
===================================================================
--- trunk/security/src/main/org/jboss/security/jndi/SecurityAssociationActions.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/jndi/SecurityAssociationActions.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.jndi;
+
+import java.security.PrivilegedAction;
+import java.security.Principal;
+import java.security.AccessController; 
+
+import javax.security.auth.Subject;
+import org.jboss.security.SecurityAssociation;
+
+/** A PrivilegedAction implementation for setting the SecurityAssociation
+ * principal and credential
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revison:$
+ */
+class SecurityAssociationActions
+{
+   private static class SetPrincipalInfoStackAction implements PrivilegedAction
+   {
+      Principal principal;
+      Object credential;
+      Subject subject;
+      SetPrincipalInfoStackAction(Principal principal, Object credential, Subject subject)
+      {
+         this.principal = principal;
+         this.credential = credential;
+         this.subject = subject;
+      }
+      public Object run()
+      {
+         SecurityAssociation.pushSubjectContext(subject, principal, credential);
+         credential = null;
+         principal = null;
+         subject = null;
+         return null;
+      }
+   }
+
+   private static class SetPrincipalInfoAction implements PrivilegedAction
+   {
+      Principal principal;
+      Object credential;
+      SetPrincipalInfoAction(Principal principal, Object credential)
+      {
+         this.principal = principal;
+         this.credential = credential;
+      }
+      public Object run()
+      {
+         SecurityAssociation.setCredential(credential);
+         credential = null;
+         SecurityAssociation.setPrincipal(principal);
+         principal = null;
+         return null;
+      }
+   }
+   private static class PopPrincipalInfoAction implements PrivilegedAction
+   {
+      public Object run()
+      {
+         SecurityAssociation.popSubjectContext();
+         return null;
+      }
+   }
+
+   private static class GetTCLAction implements PrivilegedAction
+   {
+      static PrivilegedAction ACTION = new GetTCLAction();
+      public Object run()
+      {
+         ClassLoader loader = Thread.currentThread().getContextClassLoader();
+         return loader;
+      }
+   }
+
+   private static class SetServerAction implements PrivilegedAction
+   {
+      static PrivilegedAction ACTION = new SetServerAction();
+      public Object run()
+      {
+         SecurityAssociation.setServer();
+         return null;
+      }
+   }
+   static void setPrincipalInfo(Principal principal, Object credential)
+   {
+      SetPrincipalInfoAction action = new SetPrincipalInfoAction(principal, credential);
+      AccessController.doPrivileged(action);
+   }
+   static void setPrincipalInfo(Principal principal, Object credential, Subject subject)
+   {
+      SetPrincipalInfoStackAction action = new SetPrincipalInfoStackAction(principal, credential, subject);
+      AccessController.doPrivileged(action);
+   }
+   static void popPrincipalInfo()
+   {
+      PopPrincipalInfoAction action = new PopPrincipalInfoAction();
+      AccessController.doPrivileged(action);
+   }
+
+   static void setServer()
+   {
+      AccessController.doPrivileged(SetServerAction.ACTION);
+   }
+   static ClassLoader getContextClassLoader()
+   {
+      ClassLoader loader = (ClassLoader) AccessController.doPrivileged(GetTCLAction.ACTION);
+      return loader;
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/package.html
===================================================================
--- trunk/security/src/main/org/jboss/security/package.html	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/package.html	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,4 @@
+<body>
+The basic security interfaces and classes are now located in the
+jbosssx module.
+</body>

Added: trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerService.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerService.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerService.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,259 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.plugins;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method; 
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set; 
+  
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.AuthorizationManager;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+import org.jboss.security.authorization.Resource;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.util.CachePolicy; 
+
+//$Id: AuthorizationManagerService.java 58710 2006-11-28 17:32:06Z anil.saldhana at jboss.com $
+
+/**
+ *  Service that provides Authorization capabilities.
+ *  The service defaults to the
+ *  org.jboss.security.plugins.AuthorizationManager implementation but
+ *  this can be changed via the authorizationManagerClassName property.
+ *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
+ *  @since  Jan 3, 2006 
+ *  @version $Revision: 58710 $
+ */
+public class AuthorizationManagerService 
+extends ServiceMBeanSupport
+implements AuthorizationManagerServiceMBean
+{ 
+   /** The log4j interface */
+   private static Logger log = Logger.getLogger(AuthorizationManagerService.class);
+   private static String authorizationMgrClassName = SecurityConstants.DEFAULT_AUTHORIZATION_CLASS;
+   private static Class authorizationMgrClass = JBossAuthorizationManager.class;
+   
+   private static Hashtable authorizationManagersMap = new Hashtable();
+   
+   private static int defaultCacheTimeout = 30*60;
+   private static int defaultCacheResolution = 60;
+   
+   /** The JAAS CallbackHandler interface implementation to use */
+   private static String callbackHandlerClassName = "org.jboss.security.auth.callback.SecurityAssociationHandler";
+   private static Class callbackHandlerClass = SecurityAssociationHandler.class;  
+
+   /**
+    * @see AuthorizationManagerServiceMBean#setAuthorizationManagerClassName(String)
+    */
+   public void setAuthorizationManagerClassName(String className) 
+   throws ClassNotFoundException, ClassCastException
+   {  
+      authorizationMgrClassName = className;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      authorizationMgrClass = loader.loadClass(authorizationMgrClassName);
+      if( AuthorizationManager.class.isAssignableFrom(authorizationMgrClass) == false )
+         throw new ClassCastException(authorizationMgrClass+" does not implement "+AuthorizationManager.class);
+   }
+   
+   /** Set the default CallbackHandler implementation class name
+    * @see javax.security.auth.callback.CallbackHandler
+    */
+   public void setCallbackHandlerClassName(String className)
+      throws ClassNotFoundException
+   {
+      callbackHandlerClassName = className;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      callbackHandlerClass = loader.loadClass(callbackHandlerClassName);
+   } 
+
+   /**
+    * @see AuthorizationManagerServiceMBean#getAuthorizationManagerClassName()
+    */
+   public String getAuthorizationManagerClassName()
+   {
+      return authorizationMgrClassName;
+   } 
+   
+   /**
+    * @see AuthorizationManager#doesUserHaveRole(String)
+    */
+   public boolean doesUserHaveRole(String roleName)
+   { 
+      String str = "Use getAuthorizationManager method and then call doesUserHaveRole";
+      throw new IllegalStateException(str);
+   } 
+   
+   /**
+    * @see AuthorizationManager#doesUserHaveRole(Principal, Set)
+    */
+   public boolean doesUserHaveRole(Principal principal, Set roles)
+   {
+      String str = "Use getAuthorizationManager method and then call doesUserHaveRole";
+      throw new IllegalStateException(str);
+   } 
+   
+   //ServiceMBeanSupport methods
+   protected void startService() throws Exception
+   {  
+      super.startService();
+   }
+   
+   protected void stopService() throws Exception
+   { 
+      super.stopService();
+   } 
+   
+   /** Return the set of domain roles the principal has been assigned.
+    @return The Set<Principal> for the application domain roles that the
+    principal has been assigned.
+    */
+   public Set getUserRoles(Principal principal)
+   {
+      String str = "Use getAuthorizationManager method and then call getUserRoles";
+      throw new IllegalStateException(str);
+   }
+   
+   /**
+    * @see AuthorizationManager#getPrincipal(Principal)
+    */
+   public Principal getPrincipal(Principal principal)
+   { 
+      String str = "Use getAuthorizationManager method and then call getPrincipal";
+      throw new IllegalStateException(str);
+   }
+   
+   /**
+    * @see AuthorizationManagerServiceMBean#getAuthorizationManager(String)
+    */
+   public AuthorizationManager getAuthorizationManager( String securityDomain)  
+   {
+      AuthorizationManager amanager = (AuthorizationManager)authorizationManagersMap.get(securityDomain);
+      if(amanager == null)
+      {
+         //create a new Authorization Manager 
+         amanager = newAuthorizationManager(securityDomain); 
+         authorizationManagersMap.put(securityDomain, amanager);
+         log.debug("Added "+securityDomain+", " + amanager + " to map");
+         //Add a JNDI binding based on the JaasSecurityManagerService
+         //SecurityDomainContext
+         try
+         {
+            Context ctx = new InitialContext();
+            
+            SecurityDomainContext sdc = (SecurityDomainContext)ctx.lookup("java:jaas/security/domainContext");
+            sdc.setAuthorizationManager(amanager);
+         }
+         catch (NamingException e)
+         {
+            if(log.isTraceEnabled())
+               log.trace("Error in naming", e);
+            log.error("Error in getAuthorizationManager",e); 
+         }
+      }
+      return amanager;
+   } 
+   
+   /**
+    * @see AuthorizationManager#authorize(Resource)
+    */
+   public int authorize(Resource resource)
+   {
+      String str = "Use getAuthorizationManager method and then call authorize";
+      throw new IllegalStateException(str);
+   }
+   
+   //PRIVATE METHODS 
+   
+   /** Create a new AuthorizationManager for securityDomain.
+    * @param securityDomain
+    * @return
+    * @throws NamingException
+    */
+   static AuthorizationManager newAuthorizationManager(String securityDomain) 
+   {
+      AuthorizationManager securityMgr = null;
+      try
+      {
+         // Create instance of securityMgrClass
+         Class[] parameterTypes = {String.class, CallbackHandler.class};
+         Constructor ctor = authorizationMgrClass.getConstructor(parameterTypes); 
+         CallbackHandler handler = (CallbackHandler) callbackHandlerClass.newInstance();
+         Object[] args = {securityDomain, handler}; 
+         securityMgr = (AuthorizationManager) ctor.newInstance(args); 
+         log.debug("Created AuthorizationManager="+securityMgr); 
+         
+         CachePolicy cachePolicy = JaasSecurityManagerService.lookupCachePolicy(securityDomain);
+         log.debug("Found Cache Policy="+cachePolicy);
+         /*TimedCachePolicy cachePolicy = new TimedCachePolicy(defaultCacheTimeout,
+               true, defaultCacheResolution);
+         cachePolicy.create();
+         cachePolicy.start(); */
+         // See if the security mgr supports an externalized cache policy
+         setSecurityDomainCache(securityMgr, cachePolicy); 
+      }
+      catch(Exception e2)
+      {
+         String msg = "Failed to create authz mgr('"+securityDomain+"'), authorizationMgrClass="
+         + authorizationMgrClass ;
+         log.error(msg, e2); 
+      }
+      return securityMgr;
+   } 
+   
+   /** Use reflection to attempt to set the authentication cache on the
+    * the Authorization Manager argument.
+    * @param securityMgr the Authorization Manager
+    * @param cachePolicy the cache policy implementation
+    */
+   private static void setSecurityDomainCache(AuthorizationManager securityMgr,
+         CachePolicy cachePolicy)
+   {
+      try
+      {
+         Class[] setCachePolicyTypes = {CachePolicy.class};
+         Method m = authorizationMgrClass.getMethod("setCachePolicy", setCachePolicyTypes);
+         Object[] setCachePolicyArgs = {cachePolicy};
+         m.invoke(securityMgr, setCachePolicyArgs);
+         log.debug("setCachePolicy, c="+setCachePolicyArgs[0]);
+      }
+      catch(Exception e2)
+      {   // No cache policy support, this is ok
+         if(log.isTraceEnabled())
+            log.trace("optional setCachePolicy failed:" + e2.getLocalizedMessage());
+      }
+   }
+
+   public Group getTargetRoles(Principal targetPrincipal, Map contextMap)
+   {
+      throw new RuntimeException("Not implemented"); 
+   }  
+}

Added: trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerServiceMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerServiceMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/AuthorizationManagerServiceMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,70 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.security.plugins;
+ 
+import javax.management.ObjectName;
+
+import org.jboss.mx.util.ObjectNameFactory;
+import org.jboss.security.AuthorizationManager;
+import org.jboss.system.ServiceMBean;
+
+//$Id: AuthorizationManagerServiceMBean.java 56406 2006-08-29 16:01:54Z anil.saldhana at jboss.com $
+
+/**
+ *  Management interface for the AuthorizationManagerService MBean
+ *  @author <a href="mailto:Anil.Saldhana at jboss.org">Anil Saldhana</a>
+ *  @since  Jan 2, 2006 
+ *  @version $Revision: 56406 $
+ */
+public interface AuthorizationManagerServiceMBean 
+extends ServiceMBean, AuthorizationManager
+{  
+   /** The default ObjectName */
+   ObjectName OBJECT_NAME = ObjectNameFactory.create("jboss.security:service=AuthorizationManager");
+
+   /**
+    * Set the name of the class that provides the authorization manager implementation.
+    * 
+    * @exception ClassNotFoundException thrown if the className cannot be found
+    * using the thread context class loader.
+    * @exception ClassCastException thrown if the className does not implement the
+    * org.jboss.security.AuthorizationManager interface.
+    */
+   void setAuthorizationManagerClassName(String className)
+      throws ClassNotFoundException, ClassCastException; 
+   
+   /**
+    * 
+    * Get the name of the class that provides the authorization manager implementation.
+    * 
+    * @return
+    */
+   String getAuthorizationManagerClassName();
+   
+   /**
+    * Gets an AuthorizationManager instance given a security domain
+    * 
+    * @param securityDomain
+    * @return
+    */
+   AuthorizationManager getAuthorizationManager(String securityDomain);
+}

Added: trunk/security/src/main/org/jboss/security/plugins/DefaultLoginConfig.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/DefaultLoginConfig.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/DefaultLoginConfig.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,219 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.ReflectionException;
+import javax.security.auth.login.Configuration;
+
+import org.jboss.logging.Logger;
+
+/** An mbean that uses the default JAAS login configuration file based
+ implementation. 
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 40069 $
+ */
+public class DefaultLoginConfig implements DynamicMBean
+{
+   private static Logger log = Logger.getLogger(DefaultLoginConfig.class);
+   private String authConfig = "auth.conf";
+   private Configuration theConfig;
+
+   /** Creates a new instance of DefaultLoginConfig */
+   public DefaultLoginConfig()
+   {
+   }
+
+   /** Get the resource path to the JAAS login configuration file to use.
+    */
+   public String getAuthConfig()
+   {
+      return authConfig;
+   }
+
+   /** Set the resource path or URL to the JAAS login configuration file to use.
+    The default is "auth.conf".
+    */
+   public void setAuthConfig(String authConfURL) throws MalformedURLException
+   {
+      this.authConfig = authConfURL;
+      // Set the JAAS login config file if not already set
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      URL loginConfig = loader.getResource(authConfig);
+      if( loginConfig != null )
+      {
+         System.setProperty("java.security.auth.login.config", loginConfig.toExternalForm());
+         log.info("Using JAAS LoginConfig: " + loginConfig.toExternalForm());
+      }
+      else
+      {
+         log.warn("Resource: " + authConfig + " not found");
+      }
+   }
+
+   /** Return the Configuration instance managed by this mbean. This simply
+    obtains the default Configuration by calling Configuration.getConfiguration.
+    Note that this means this mbean must be the first pushed onto the config
+    stack if it is used.
+    @see javax.security.auth.login.Configuration
+    */
+   public Configuration getConfiguration(Configuration currentConfig)
+   {
+      if( theConfig == null )
+      {
+         theConfig = Configuration.getConfiguration();
+         log.debug("theConfig set to: "+theConfig);
+      }
+      return theConfig;
+   }
+
+// Begin DynamicMBean interfaces
+   public Object getAttribute(String name)
+      throws AttributeNotFoundException, MBeanException, ReflectionException
+   {
+      if( name.equals("AuthConfig") )
+         return getAuthConfig();
+      throw new AttributeNotFoundException(name+": is not an attribute");
+   }
+
+   public AttributeList getAttributes(String[] names)
+   {
+      AttributeList list = new AttributeList();
+      for(int n = 0; n < names.length; n ++)
+      {
+         String name = names[n];
+         try
+         {
+            Object value = getAttribute(name);
+            Attribute attr = new Attribute(name, value);
+            list.add(attr);
+         }
+         catch(Exception e)
+         {
+         }
+      }
+      return list;
+   }
+
+   public MBeanInfo getMBeanInfo()
+   {
+      Class c = getClass();
+      MBeanAttributeInfo[] attrInfo = {
+         new MBeanAttributeInfo("AuthConfig", "java.lang.String",
+             "", true, true, false)
+      };
+      Constructor ctor = null;
+      try
+      {
+         Class[] sig = {};
+         ctor = c.getDeclaredConstructor(sig);
+      }
+      catch(Exception e)
+      {
+      }
+      MBeanConstructorInfo[] ctorInfo = {
+         new MBeanConstructorInfo("Default ctor", ctor)
+      };
+      Method getConfiguration = null;
+      try
+      {
+         Class[] sig = {Configuration.class};
+         getConfiguration = c.getDeclaredMethod("getConfiguration", sig);
+      }
+      catch(Exception e)
+      {
+      }
+      MBeanOperationInfo[] opInfo = {
+         new MBeanOperationInfo("Access the LoginConfiguration", getConfiguration)
+      };
+      MBeanInfo info = new MBeanInfo(c.getName(), "Default JAAS LoginConfig",
+         attrInfo, ctorInfo, opInfo, null);
+      return info;
+   }
+
+   public Object invoke(String method, Object[] args, String[] signature)
+      throws MBeanException, ReflectionException
+   {
+      Object value = null;
+      if( method.equals("getConfiguration") )
+      {
+         Configuration currentConfig = (Configuration) args[0];
+         value = this.getConfiguration(currentConfig);
+      }
+      return value;
+   }
+
+   public void setAttribute(Attribute attribute)
+      throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
+   {
+      String name = attribute.getName();
+      String value = (String) attribute.getValue();
+      if( name.equals("AuthConfig") )
+      {
+         try
+         {
+            setAuthConfig(value);
+         }
+         catch(Exception e)
+         {
+            throw new MBeanException(e);
+         }
+      }
+      else
+         throw new AttributeNotFoundException(name+": is not an attribute");      
+   }
+
+   public AttributeList setAttributes(AttributeList attributeList)
+   {
+      AttributeList list = new AttributeList();
+      for(int n = 0; n < attributeList.size(); n ++)
+      {
+         Attribute attr = (Attribute) attributeList.get(n);
+         try
+         {
+            setAttribute(attr);
+            list.add(attr);
+         }
+         catch(Exception e)
+         {
+         }
+      }
+      return list;
+   }
+// End DynamicMBean interfaces
+
+}

Added: trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomain.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomain.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomain.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,575 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.KeyStore;
+import java.util.Arrays;
+import java.util.StringTokenizer;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.jboss.mx.util.MBeanServerLocator;
+import org.jboss.security.SecurityDomain;
+import org.jboss.crypto.CryptoUtil;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+
+/** The JaasSecurityDomain is an extension of JaasSecurityManager that addes
+ the notion of a KeyStore, and JSSE KeyManagerFactory and TrustManagerFactory
+ for supporting SSL and other cryptographic use cases.
+ 
+ Attributes:
+ <ul>
+ <li>KeyStoreType: The implementation type name being used, defaults to 'JKS'.
+ </li>
+
+ <li>KeyStoreURL: Set the KeyStore database URL string. This is used to obtain
+ an InputStream to initialize the KeyStore. If the string is not a value
+ URL, its treated as a file.
+ </li>
+ 
+ <li>KeyStorePass: the password used to load the KeyStore. Its format is one of:
+ <ul>
+ <li>The plaintext password for the KeyStore(or whatever format is used
+ by the KeyStore). The toCharArray() value of the string is used without any
+ manipulation.
+ </li>
+ <li>A command to execute to obtain the plaintext password. The format
+ is '{EXT}...' where the '...' is the exact command line that will be passed
+ to the Runtime.exec(String) method to execute a platform command. The first
+ line of the command output is used as the password.
+ </li>
+ <li>A class to create to obtain the plaintext password. The format
+ is '{CLASS}classname[:ctorarg]' where the '[:ctorarg]' is an optional
+ string delimited by the ':' from the classname that will be passed to the
+ classname ctor. The password is obtained from classname by invoking a 'char[]
+ toCharArray()' method if found, otherwise, the 'String toString()' method is
+ used.
+ </li> 
+ </ul>
+ The KeyStorePass is also used in combination with the Salt and IterationCount
+ attributes to create a PBE secret key used with the encode/decode operations.
+ </li>
+
+ <li>ManagerServiceName: The JMX object name string of the security manager service
+ that the domain registers with to function as a security manager for the
+ security domain name passed to the ctor. The makes the JaasSecurityDomain
+ available under the standard JNDI java:/jaas/(domain) binding.
+ </li>
+
+ <li>LoadSunJSSEProvider: A flag indicating if the Sun com.sun.net.ssl.internal.ssl.Provider 
+ security provider should be loaded on startup. This is needed when using
+ the Sun JSSE jars without them installed as an extension with JDK 1.3. This
+ should be set to false with JDK 1.4 or when using an alternate JSSE provider
+ </li>
+
+ <li>Salt:
+ </li>
+ 
+ <li>IterationCount:
+ </li>
+ </ul>
+
+ @todo add support for encode/decode based on a SecretKey in the keystore.
+ 
+ @author Scott.Stark at jboss.org
+ @author <a href="mailto:jasone at greenrivercomputing.com">Jason Essington</a>
+
+ @version $Revision: 37459 $
+ */
+public class JaasSecurityDomain
+   extends JaasSecurityManager
+   implements SecurityDomain, JaasSecurityDomainMBean
+{
+   /** The permission required to access encode, encode64 */
+   private static final RuntimePermission encodePermission =
+      new RuntimePermission("org.jboss.security.plugins.JaasSecurityDomain.encode");
+   /** The permission required to access decode, decode64 */
+   private static final RuntimePermission decodePermission =
+      new RuntimePermission("org.jboss.security.plugins.JaasSecurityDomain.decode");
+
+   /** The KeyStore associated with the security domain */
+   private KeyStore keyStore;
+   private KeyManagerFactory keyMgr;
+   /** The KeyStore implementation type which defaults to 'JKS' */
+   private String keyStoreType = "JKS";
+   /** The resource for the keystore location */
+   private URL keyStoreURL;
+   /** The keystore password for loading */
+   private char[] keyStorePassword;
+   /** A command string to execute to obtain the keyStorePassword */
+   private String keyStorePasswordCmd;
+   /** The type of command string: EXT, CLASS */
+   private String keyStorePasswordCmdType;
+   /** The secret key that corresponds to the keystore password */
+   private SecretKey cipherKey;
+   /** The encode/decode cipher algorigthm */
+   private String cipherAlgorithm = "PBEwithMD5andDES";
+   private byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8};
+   private int iterationCount = 103;
+   private PBEParameterSpec cipherSpec;
+   /** The JMX object name of the security manager service */
+   private ObjectName managerServiceName = JaasSecurityManagerServiceMBean.OBJECT_NAME;
+
+   private KeyStore trustStore;
+   private String trustStoreType = "JKS";
+   private char[] trustStorePassword;
+   private URL trustStoreURL;
+   private TrustManagerFactory trustMgr;
+
+   /** Creates a default JaasSecurityDomain for with a securityDomain
+    name of 'other'.
+    */
+   public JaasSecurityDomain()
+   {
+      super();
+   }
+
+   /** Creates a JaasSecurityDomain for with a securityDomain
+    name of that given by the 'securityDomain' argument.
+    @param securityDomain , the name of the security domain
+    */
+   public JaasSecurityDomain(String securityDomain)
+   {
+      this(securityDomain, new SecurityAssociationHandler());
+   }
+
+   /** Creates a JaasSecurityDomain for with a securityDomain
+    name of that given by the 'securityDomain' argument.
+    @param securityDomain , the name of the security domain
+    @param handler , the CallbackHandler to use to obtain login module info
+    */
+   public JaasSecurityDomain(String securityDomain, CallbackHandler handler)
+   {
+      super(securityDomain, handler);
+   }
+
+   public KeyStore getKeyStore() throws SecurityException
+   {
+      return keyStore;
+   }
+
+   public KeyManagerFactory getKeyManagerFactory() throws SecurityException
+   {
+      return keyMgr;
+   }
+
+   public KeyStore getTrustStore() throws SecurityException
+   {
+      return trustStore;
+   }
+
+   public TrustManagerFactory getTrustManagerFactory() throws SecurityException
+   {
+      return trustMgr;
+   }
+
+   /** The JMX object name string of the security manager service.
+    @return The JMX object name string of the security manager service.
+    */
+   public ObjectName getManagerServiceName()
+   {
+      return this.managerServiceName;
+   }
+
+   /** Set the JMX object name string of the security manager service.
+    */
+   public void setManagerServiceName(ObjectName managerServiceName)
+   {
+      this.managerServiceName = managerServiceName;
+   }
+
+   public String getKeyStoreType()
+   {
+      return this.keyStoreType;
+   }
+
+   public void setKeyStoreType(String type)
+   {
+      this.keyStoreType = type;
+   }
+
+   public String getKeyStoreURL()
+   {
+      String url = null;
+      if( keyStoreURL != null )
+         url = keyStoreURL.toExternalForm();
+      return url;
+   }
+
+   public void setKeyStoreURL(String storeURL) throws IOException
+   {
+      this.keyStoreURL = this.validateStoreURL(storeURL);
+      log.debug("Using KeyStore=" + keyStoreURL.toExternalForm());
+   }
+
+   public void setKeyStorePass(String password)
+   {
+      this.keyStorePassword = null;
+      // Look for a {...} prefix indicating a password command
+      if( password.charAt(0) == '{' )
+      {
+         StringTokenizer tokenizer = new StringTokenizer(password, "{}");
+         this.keyStorePasswordCmdType = tokenizer.nextToken();
+         this.keyStorePasswordCmd = tokenizer.nextToken();
+      }
+      else
+      {
+         // Its just the keystore password string
+         this.keyStorePassword = password.toCharArray();
+      }
+   }
+
+   public String getTrustStoreType()
+   {
+      return this.trustStoreType;
+   }
+
+   public void setTrustStoreType(String type)
+   {
+      this.trustStoreType = type;
+   }
+
+   public void setTrustStorePass(String password)
+   {
+      this.trustStorePassword = password.toCharArray();
+   }
+
+   public String getTrustStoreURL()
+   {
+      String url = null;
+      if( trustStoreURL != null )
+         url = trustStoreURL.toExternalForm();
+      return url;
+   }
+
+   public void setTrustStoreURL(String storeURL) throws IOException
+   {
+      this.trustStoreURL = validateStoreURL(storeURL);
+   }
+
+   public void setSalt(String salt)
+   {
+      this.salt = salt.getBytes();
+   }
+
+   public void setIterationCount(int iterationCount)
+   {
+      this.iterationCount = iterationCount;
+   }
+
+   public String getCipherAlgorithm()
+   {
+      return cipherAlgorithm;
+   }
+
+   public void setCipherAlgorithm(String cipherAlgorithm)
+   {
+      this.cipherAlgorithm = cipherAlgorithm;
+   }
+
+   public String getName()
+   {
+      return "JaasSecurityDomain(" + getSecurityDomain() + ")";
+   }
+
+   /** Encrypt the secret using the cipherKey.
+    * @param secret - the plaintext secret to encrypt
+    * @return the encrypted secret
+    * @throws Exception
+    */ 
+   public byte[] encode(byte[] secret)
+      throws Exception
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if( sm != null )
+      {
+         System.out.println("Checking: "+encodePermission);
+         sm.checkPermission(encodePermission);
+      }
+
+      Cipher cipher = Cipher.getInstance(cipherAlgorithm);
+      cipher.init(Cipher.ENCRYPT_MODE, cipherKey, cipherSpec);
+      byte[] encoding = cipher.doFinal(secret);
+      return encoding;
+   }
+   /** Decrypt the secret using the cipherKey.
+    * 
+    * @param secret - the encrypted secret to decrypt.
+    * @return the decrypted secret
+    * @throws Exception
+    */ 
+   public byte[] decode(byte[] secret)
+      throws Exception
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if( sm != null )
+         sm.checkPermission(decodePermission);
+
+      Cipher cipher = Cipher.getInstance(cipherAlgorithm);
+      cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherSpec);
+      byte[] decode = cipher.doFinal(secret);
+      return decode;
+   }
+   /** Encrypt the secret using the cipherKey and return a base64 encoding.
+    * @param secret - the plaintext secret to encrypt
+    * @return the encrypted secret as a base64 string
+    * @throws Exception
+    */ 
+   public String encode64(byte[] secret)
+      throws Exception
+   {
+      byte[] encoding = encode(secret);
+      String b64 = CryptoUtil.tob64(encoding);
+      return b64;
+   }
+   /** Decrypt the base64 encoded secret using the cipherKey.
+    * 
+    * @param secret - the base64 encoded encrypted secret to decrypt.
+    * @return the decrypted secret
+    * @throws Exception
+    */
+   public byte[] decode64(String secret)
+      throws Exception
+   {
+      byte[] encoding = CryptoUtil.fromb64(secret);
+      byte[] decode = decode(encoding);
+      return decode;
+   }
+
+   /**
+       Reload the key- and truststore
+   */
+   public void reloadKeyAndTrustStore()
+      throws Exception
+   {
+      loadKeyAndTrustStore();
+   }
+
+   protected void startService()
+      throws Exception
+   {
+      // Load the keystore password if it was 
+      loadKeystorePassword();
+
+      // Load the key and/or truststore into memory
+      loadKeyAndTrustStore();
+
+      // Only register with the JaasSecurityManagerService if its defined
+      if( managerServiceName != null )
+      {
+         /* Register with the JaasSecurityManagerServiceMBean. This allows this
+          JaasSecurityDomain to function as the security manager for security-domain
+          elements that declare java:/jaas/xxx for our security domain name.
+          */
+         MBeanServer server = MBeanServerLocator.locateJBoss();
+         Object[] params = {getSecurityDomain(), this};
+         String[] signature = new String[]{"java.lang.String", "org.jboss.security.SecurityDomain"};
+         server.invoke(managerServiceName, "registerSecurityDomain", params, signature);
+      }
+   }
+
+   protected void stopService()
+   {
+      if( keyStorePassword != null )
+      {
+         Arrays.fill(keyStorePassword, '\0');
+         keyStorePassword = null;
+      }
+      cipherKey = null;
+   }
+
+   /** If keyStorePassword is null and keyStorePasswordCmd exists,
+    * execute it to obtain the password.
+    */ 
+   private void loadKeystorePassword()
+      throws Exception
+   {
+      if( keyStorePassword == null )
+      {
+         if( keyStorePasswordCmdType.equals("EXT") )
+            execPasswordCmd();
+         else if( keyStorePasswordCmdType.equals("CLASS") )
+            invokePasswordClass();
+         else
+            throw new IllegalArgumentException("Unknown keyStorePasswordCmdType: "+keyStorePasswordCmdType);
+      }
+
+      // Create the PBE secret key
+      cipherSpec = new PBEParameterSpec(salt, iterationCount);
+      PBEKeySpec keySpec = new PBEKeySpec(keyStorePassword);
+      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES");
+      cipherKey = factory.generateSecret(keySpec);
+   }
+   
+   private void loadKeyAndTrustStore()
+      throws Exception
+   {
+      if( keyStoreURL != null )
+      {
+         keyStore = KeyStore.getInstance(keyStoreType);
+         InputStream is = keyStoreURL.openStream();
+         keyStore.load(is, keyStorePassword);
+         String algorithm = KeyManagerFactory.getDefaultAlgorithm();
+         keyMgr = KeyManagerFactory.getInstance(algorithm);
+         keyMgr.init(keyStore, keyStorePassword);
+      }
+      if( trustStoreURL != null )
+      {
+         trustStore = KeyStore.getInstance(trustStoreType);
+         InputStream is = trustStoreURL.openStream();
+         trustStore.load(is, trustStorePassword);
+         String algorithm = TrustManagerFactory.getDefaultAlgorithm();
+         trustMgr = TrustManagerFactory.getInstance(algorithm);
+         trustMgr.init(trustStore);
+      }
+      else if( keyStore != null )
+      {
+         trustStore = keyStore;
+         String algorithm = TrustManagerFactory.getDefaultAlgorithm();
+         trustMgr = TrustManagerFactory.getInstance(algorithm);
+         trustMgr.init(trustStore);         
+      }
+   }
+
+   private void execPasswordCmd()
+      throws Exception
+   {
+      log.debug("Executing command: "+keyStorePasswordCmd);
+      Runtime rt = Runtime.getRuntime();
+      Process p = rt.exec(keyStorePasswordCmd);
+      InputStream stdin = p.getInputStream();
+      BufferedReader reader = new BufferedReader(new InputStreamReader(stdin));
+      String password = reader.readLine();
+      stdin.close();
+      int exitCode = p.waitFor();
+      log.debug("Command exited with: "+exitCode);
+      keyStorePassword = password.toCharArray();
+   }
+   /**
+    * 
+    * @throws Exception
+    */ 
+   private void invokePasswordClass()
+      throws Exception
+   {
+      keyStorePassword = null;
+
+      // Check for a ctor argument delimited by ':'
+      String classname = keyStorePasswordCmd;
+      String ctorArg = null;
+      int colon = keyStorePasswordCmd.indexOf(':');
+      if( colon > 0 )
+      {
+         classname = keyStorePasswordCmd.substring(0, colon);
+         ctorArg = keyStorePasswordCmd.substring(colon+1);
+      }
+      log.debug("Loading class: "+classname+", ctorArg="+ctorArg);
+      ClassLoader loader = SubjectActions.getContextClassLoader();
+      Class c = loader.loadClass(classname);
+      Object instance = null;
+      // Check for a ctor(String) if ctorArg is not null
+      if( ctorArg != null )
+      {
+         Class[] sig = {String.class};
+         Constructor ctor = c.getConstructor(sig);
+         Object[] args = {ctorArg};
+         instance = ctor.newInstance(args);
+      }
+      else
+      {
+         // Use the default ctor
+         instance = c.newInstance();
+      }
+
+      // Look for a toCharArray() method
+      try
+      {
+         log.debug("Checking for toCharArray");
+         Class[] sig = {};
+         Method toCharArray = c.getMethod("toCharArray", sig);
+         Object[] args = {};
+         log.debug("Invoking toCharArray");
+         keyStorePassword = (char[]) toCharArray.invoke(instance, args);
+      }
+      catch(NoSuchMethodException e)
+      {
+         log.debug("No toCharArray found, invoking toString");
+         String tmp = instance.toString();
+         if( tmp != null )
+            keyStorePassword = tmp.toCharArray();
+      }
+   }
+
+   private URL validateStoreURL(String storeURL) throws IOException
+   {
+      URL url = null;
+      // First see if this is a URL
+      try
+      {
+         url = new URL(storeURL);
+      }
+      catch(MalformedURLException e)
+      {
+         // Not a URL or a protocol without a handler
+      }
+
+      // Next try to locate this as file path
+      if( url == null )
+      {
+         File tst = new File(storeURL);
+         if( tst.exists() == true )
+            url = tst.toURL();
+      }
+
+      // Last try to locate this as a classpath resource
+      if( url == null )
+      {
+         ClassLoader loader = SubjectActions.getContextClassLoader();
+         url = loader.getResource(storeURL);
+      }
+
+      // Fail if no valid key store was located
+      if( url == null )
+      {
+         String msg = "Failed to find url=" + storeURL + " as a URL, file or resource";
+         throw new MalformedURLException(msg);
+      }
+      return url;
+   }
+}

Added: trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomainMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomainMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/JaasSecurityDomainMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,127 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.io.IOException;
+import javax.management.ObjectName;
+import org.jboss.system.ServiceMBean;
+
+
+/** The JaasSecurityDomainMBean adds support for KeyStore management.
+
+ @author Scott.Stark at jboss.org
+ @author <a href="mailto:jasone at greenrivercomputing.com">Jason Essington</a>
+ @version $Revision: 37459 $
+*/
+public interface JaasSecurityDomainMBean extends ServiceMBean
+{
+   /** KeyStore implementation type being used.
+    @return the KeyStore implementation type being used.
+    */
+   public String getKeyStoreType();
+   /** Set the type of KeyStore implementation to use. This is
+    passed to the KeyStore.getInstance() factory method.
+    */
+   public void setKeyStoreType(String type);
+   /** Get the KeyStore database URL string.
+    */
+   public String getKeyStoreURL();
+   /** Set the KeyStore database URL string. This is used to obtain
+    an InputStream to initialize the KeyStore.
+    */
+   public void setKeyStoreURL(String storeURL) throws IOException;
+    /** Set the credential string for the KeyStore.
+    */
+   public void setKeyStorePass(String password);
+
+   /** Get the type of the trust store
+    * @return the type of the trust store
+    */ 
+   public String getTrustStoreType();
+   /** Set the type of the trust store
+    * @param type - the trust store implementation type
+    */ 
+   public void setTrustStoreType(String type);
+   /** Set the credential string for the trust store.
+   */
+   public void setTrustStorePass(String password);   
+   /** Get the trust store database URL string.
+    */
+   public String getTrustStoreURL();
+   /** Set the trust store database URL string. This is used to obtain
+    an InputStream to initialize the trust store.
+    */
+   public void setTrustStoreURL(String storeURL) throws IOException;
+   /**
+       Reload the key- and truststore
+   */
+   public void reloadKeyAndTrustStore() throws Exception;
+   /** The JMX object name string of the security manager service.
+    @return The JMX object name string of the security manager service.
+    */
+   public ObjectName getManagerServiceName();
+   /** Set the JMX object name string of the security manager service.
+    */
+   public void setManagerServiceName(ObjectName jmxName);
+
+   /** Set the salt used with PBE based on the keystore password.
+    * @param salt - an 8 char randomization string
+    */ 
+   public void setSalt(String salt);
+   /** Set the iteration count used with PBE based on the keystore password.
+    * @param count - an iteration count randomization value
+    */ 
+   public void setIterationCount(int count);
+
+   /** Encode a secret using the keystore password and PBEwithMD5andDES algo
+    * @param secret - the byte sequence to encrypt
+    * @return the encrypted byte sequence
+    * @throws Exception
+    */ 
+   public byte[] encode(byte[] secret)
+      throws Exception;
+
+   /** Decode a secret using the keystore password and PBEwithMD5andDES algo
+    * @param secret - the byte sequence to decrypt
+    * @return the decrypted byte sequence
+    * @throws Exception
+    */ 
+   public byte[] decode(byte[] secret)
+      throws Exception;
+
+   /** Encode a secret using the keystore password and PBEwithMD5andDES algo
+    * @param secret - the byte sequence to encrypt as a base64 string using
+    *    the Util.tob64() function
+    * @return the encrypted byte sequence
+    * @throws Exception
+    */    
+   public String encode64(byte[] secret)
+      throws Exception;
+
+   /** Decode a secret using the keystore password and PBEwithMD5andDES algo
+    * @param secret - the Util.tob64 string represention to decrypt
+    * @return the decrypted byte sequence
+    * @throws Exception
+    */ 
+   public byte[] decode64(String secret)
+      throws Exception;
+}

Added: trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManager.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManager.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManager.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,722 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Arrays;
+import java.util.Enumeration;  
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.logging.Logger; 
+import org.jboss.security.AuthorizationManager; 
+import org.jboss.security.RealmMapping; 
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityUtil;
+import org.jboss.security.SubjectSecurityManager;
+import org.jboss.security.auth.callback.SecurityAssociationHandler;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.util.CachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+/** The JaasSecurityManager is responsible both for authenticating credentials
+ associated with principals and for role mapping. This implementation relies
+ on the JAAS LoginContext/LoginModules associated with the security
+ domain name associated with the class for authentication,
+ and the context JAAS Subject object for role mapping.
+ 
+ @see #isValid(Principal, Object, Subject)
+ @see #getPrincipal(Principal)
+ @see #doesUserHaveRole(Principal, Set)
+ 
+ @author <a href="on at ibis.odessa.ua">Oleg Nitz</a>
+ @author Scott.Stark at jboss.org
+ @author Anil.Saldhana at jboss.org
+ @version $Revision: 62860 $
+*/
+public class JaasSecurityManager extends ServiceMBeanSupport
+   implements SubjectSecurityManager, RealmMapping
+{
+   /** The authentication cache object.
+    */
+   public static class DomainInfo implements TimedCachePolicy.TimedEntry
+   {
+      private static Logger log = Logger.getLogger(DomainInfo.class);
+      private static boolean trace = log.isTraceEnabled();
+      private LoginContext loginCtx;
+      private Subject subject;
+      private Object credential;
+      private Principal callerPrincipal;
+      private long expirationTime;
+      /** Is there an active authentication in process */
+      private boolean needsDestroy;
+      /** The number of users sharing this DomainInfo */
+      private int activeUsers;
+
+      /**
+       Create a cache entry with the given lifetime in seconds. Since this comes
+       from the TimedCachePolicy, its expected to be <= Integer.MAX_VALUE.
+       
+       @param lifetime - lifetime in seconds. A lifetime <= 0 means no caching
+         with the exception of -1 which indicates that the cache entry never
+         expires.
+       */
+      public DomainInfo(long lifetime)
+      {
+         expirationTime = lifetime;
+         if( expirationTime != -1 )
+            expirationTime *= 1000;
+      }
+
+      synchronized int acquire()
+      {
+         return activeUsers ++;
+      }
+      synchronized int release()
+      {
+         int users = activeUsers --;
+         if( needsDestroy == true && users == 0 )
+         {
+            if( trace )
+               log.trace("needsDestroy is true, doing logout");
+            logout();
+         }
+         return users;
+      }
+      synchronized void logout()
+      {
+         if( trace )
+            log.trace("logout, subject="+subject+", this="+this);
+         try
+         {
+            if( loginCtx != null )
+               loginCtx.logout();
+         }
+         catch(Throwable e)
+         {
+            if( trace )
+               log.trace("Cache entry logout failed", e);
+         }
+      }
+
+      public void init(long now)
+      {
+         expirationTime += now;
+      }
+      public boolean isCurrent(long now)
+      {
+         boolean isCurrent = expirationTime == -1;
+         if( isCurrent == false )
+            isCurrent = expirationTime > now;
+         return isCurrent;
+      }
+      public boolean refresh()
+      {
+         return false;
+      }
+      /**
+       * This 
+       */ 
+      public void destroy()
+      {
+         if( trace )
+         {
+            log.trace("destroy, subject="+subject+", this="+this
+               +", activeUsers="+activeUsers);
+         }
+
+         synchronized( this )
+         {
+            if( activeUsers == 0 )
+               logout();
+            else
+            {
+               if( trace )
+                  log.trace("destroy saw activeUsers="+activeUsers);
+               needsDestroy = true;
+            }
+         }
+      }
+      public Object getValue()
+      {
+         return this;
+      }
+      public String toString()
+      {
+         StringBuffer tmp = new StringBuffer(super.toString());
+         tmp.append('[');
+         tmp.append(SubjectActions.toString(subject));
+         tmp.append(",credential.class=");
+         if( credential != null )
+         {
+            Class c = credential.getClass();
+            tmp.append(c.getName());
+            tmp.append('@');
+            tmp.append(System.identityHashCode(c));
+         }
+         else
+         {
+            tmp.append("null");
+         }
+         tmp.append(",expirationTime=");
+         tmp.append(expirationTime);
+         tmp.append(']');
+
+         return tmp.toString();
+      }
+   }
+
+   /** The name of the domain this instance is securing. It is used as
+    the appName into the SecurityPolicy.
+    */
+   private String securityDomain;
+   /** A cache of DomainInfo objects keyd by Principal. This is now
+    always set externally by our security manager service.
+    */
+   private CachePolicy domainCache;
+   /** The JAAS callback handler to use in defaultLogin */
+   private CallbackHandler handler;
+   /** The setSecurityInfo(Principal, Object) method of the handler obj */
+   private Method setSecurityInfo;
+   /** The flag to indicate that the Subject sets need to be deep copied*/
+   private boolean deepCopySubjectOption = false; 
+   
+   /** The log4j category for the security manager domain
+    */
+   protected Logger log;
+   protected boolean trace;
+
+   /** Creates a default JaasSecurityManager for with a securityDomain
+    name of 'other'.
+    */
+   public JaasSecurityManager()
+   {
+      this("other", new SecurityAssociationHandler());
+   }
+   /** Creates a JaasSecurityManager for with a securityDomain
+    name of that given by the 'securityDomain' argument.
+    @param securityDomain the name of the security domain
+    @param handler the JAAS callback handler instance to use
+    @exception UndeclaredThrowableException thrown if handler does not
+      implement a setSecurityInfo(Princpal, Object) method
+    */
+   public JaasSecurityManager(String securityDomain, CallbackHandler handler)
+   {
+      this.securityDomain = securityDomain;
+      this.handler = handler;
+      String categoryName = getClass().getName()+'.'+securityDomain;
+      this.log = Logger.getLogger(categoryName);
+      this.trace = log.isTraceEnabled();
+
+      // Get the setSecurityInfo(Principal principal, Object credential) method
+      Class[] sig = {Principal.class, Object.class};
+      try
+      {
+         setSecurityInfo = handler.getClass().getMethod("setSecurityInfo", sig);
+      }
+      catch (Exception e)
+      {
+         String msg = "Failed to find setSecurityInfo(Princpal, Object) method in handler";
+         throw new UndeclaredThrowableException(e, msg);
+      } 
+      log.debug("CallbackHandler: "+handler);
+   }
+
+   /** The domainCache is typically a shared object that is populated
+    by the login code(LoginModule, etc.) and read by this class in the
+    isValid() method.
+    @see #isValid(Principal, Object, Subject)
+    */
+   public void setCachePolicy(CachePolicy domainCache)
+   {
+      this.domainCache = domainCache;
+      log.debug("CachePolicy set to: "+domainCache);
+   }
+
+   /**
+    * Flag to specify if deep copy of subject sets needs to be 
+    * enabled
+    * 
+    * @param flag
+    */
+   public void setDeepCopySubjectOption(Boolean flag)
+   {
+      log.debug("setDeepCopySubjectOption="+ flag);
+      this.deepCopySubjectOption = (flag == Boolean.TRUE) ;
+   } 
+   
+   /** Not really used anymore as the security manager service manages the
+    security domain authentication caches.
+    */
+   public void flushCache()
+   {
+      if( domainCache != null )
+         domainCache.flush();
+   }
+
+   /** Get the name of the security domain associated with this security mgr.
+    @return Name of the security manager security domain.
+    */
+   public String getSecurityDomain()
+   {
+      return securityDomain;
+   }
+
+   /** Get the currently authenticated Subject. This is a thread local
+    property shared across all JaasSecurityManager instances.
+    @return The Subject authenticated in the current thread if one
+    exists, null otherwise.
+    */
+   public Subject getActiveSubject()
+   {
+      /* This does not use SubjectActions.getActiveSubject since the caller
+         must have the correct permissions to access the
+         SecurityAssociation.getSubject method.
+      */
+      //return SecurityAssociation.getSubject();
+      Subject subj = null;
+      SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+      if(sc != null)
+      {
+         subj = sc.getUtil().getSubject();
+      }
+      return subj;
+   }
+
+   /** Validate that the given credential is correct for principal. This
+    returns the value from invoking isValid(principal, credential, null).
+    @param principal - the security domain principal attempting access
+    @param credential - the proof of identity offered by the principal
+    @return true if the principal was authenticated, false otherwise.
+    */
+   public boolean isValid(Principal principal, Object credential)
+   {
+      return isValid(principal, credential, null);
+   }
+
+   /** Validate that the given credential is correct for principal. This first
+    will check the current CachePolicy object if one exists to see if the
+    user's cached credentials match the given credential. If there is no
+    credential cache or the cache information is invalid or does not match,
+    the user is authenticated against the JAAS login modules configured for
+    the security domain.
+    @param principal - the security domain principal attempting access
+    @param credential  the proof of identity offered by the principal
+    @param activeSubject - if not null, a Subject that will be populated with
+      the state of the authenticated Subject.
+    @return true if the principal was authenticated, false otherwise.
+    */
+   public boolean isValid(Principal principal, Object credential,
+      Subject activeSubject)
+   {
+      // Check the cache first
+      DomainInfo cacheInfo = getCacheInfo(principal, true);
+      if( trace )
+         log.trace("Begin isValid, principal:"+principal+", cache info: "+cacheInfo);
+
+      boolean isValid = false;
+      if( cacheInfo != null )
+      {
+         isValid = validateCache(cacheInfo, credential, activeSubject);
+         if( cacheInfo != null )
+            cacheInfo.release();
+      }
+      if( isValid == false )
+         isValid = authenticate(principal, credential, activeSubject);
+      if( trace )
+         log.trace("End isValid, "+isValid); 
+      return isValid;
+   }
+
+   /** Map the argument principal from the deployment environment principal
+    to the developer environment. This is called by the EJB context
+    getCallerPrincipal() to return the Principal as described by
+    the EJB developer domain.
+    @return a Principal object that is valid in the deployment environment
+    if one exists. If no Subject exists or the Subject has no principals
+    then the argument principal is returned.
+    */
+   public Principal getPrincipal(Principal principal)
+   {
+      if(domainCache == null)
+         return principal;
+      Principal result = principal; 
+      // Get the CallerPrincipal group member
+      synchronized( domainCache )
+      {
+         DomainInfo info = getCacheInfo(principal, false);
+         if( trace )
+            log.trace("getPrincipal, cache info: "+info);
+         if( info != null )
+         {
+            result = info.callerPrincipal;
+            // If the mapping did not have a callerPrincipal just use principal
+            if( result == null )
+               result = principal;
+            info.release();
+         }
+      }
+
+      return result;
+   }
+
+   /** Does the current Subject have a role(a Principal) that equates to one
+    of the role names. This method obtains the Group named 'Roles' from
+    the principal set of the currently authenticated Subject as determined
+    by the SecurityAssociation.getSubject() method and then creates a
+    SimplePrincipal for each name in roleNames. If the role is a member of the
+    Roles group, then the user has the role. This requires that the caller
+    establish the correct SecurityAssociation subject prior to calling this
+    method. In the past this was done as a side-effect of an isValid() call,
+    but this is no longer the case.
+
+    @param principal - ignored. The current authenticated Subject determines
+    the active user and assigned user roles.
+    @param rolePrincipals - a Set of Principals for the roles to check.
+    
+    @see java.security.acl.Group;
+    @see Subject#getPrincipals()
+    */
+   public boolean doesUserHaveRole(Principal principal, Set rolePrincipals)
+   { 
+      AuthorizationManager am = SecurityUtil.getAuthorizationManager(securityDomain);
+      return am.doesUserHaveRole(principal, rolePrincipals); 
+   } 
+
+   /** Return the set of domain roles the current active Subject 'Roles' group
+      found in the subject Principals set.
+
+    @param principal - ignored. The current authenticated Subject determines
+    the active user and assigned user roles.
+    @return The Set<Principal> for the application domain roles that the
+    principal has been assigned.
+   */
+   public Set getUserRoles(Principal principal)
+   {
+      AuthorizationManager am = SecurityUtil.getAuthorizationManager(securityDomain);
+      return am.getUserRoles(principal);
+   } 
+   
+   /**
+    * @see AuthenticationManager#getTargetPrincipal(Principal,Map)
+    */
+   public Principal getTargetPrincipal(Principal anotherDomainPrincipal, Map contextMap)
+   {
+      throw new RuntimeException("Not implemented yet");
+   }
+
+   /** Currently this simply calls defaultLogin() to do a JAAS login using the
+    security domain name as the login module configuration name.
+    
+    * @param principal - the user id to authenticate
+    * @param credential - an opaque credential.
+    * @return false on failure, true on success.
+    */
+   private boolean authenticate(Principal principal, Object credential,
+      Subject theSubject)
+   {
+      Subject subject = null;
+      boolean authenticated = false;
+      LoginException authException = null;
+
+      try
+      {
+         // Validate the principal using the login configuration for this domain
+         LoginContext lc = defaultLogin(principal, credential);
+         subject = lc.getSubject();
+
+         // Set the current subject if login was successful
+         if( subject != null )
+         {
+            // Copy the current subject into theSubject
+            if( theSubject != null )
+            {
+               SubjectActions.copySubject(subject, theSubject, false,this.deepCopySubjectOption);
+            }
+            else
+            {
+               theSubject = subject;
+            }
+
+            authenticated = true;
+            // Build the Subject based DomainInfo cache value
+            updateCache(lc, subject, principal, credential);
+         }
+      }
+      catch(LoginException e)
+      {
+         // Don't log anonymous user failures unless trace level logging is on
+         if( principal != null && principal.getName() != null || trace )
+            log.trace("Login failure", e);
+         authException = e;
+      }
+      // Set the security association thread context info exception
+      SubjectActions.setContextInfo("org.jboss.security.exception", authException);
+
+      return authenticated;
+   }
+
+   /** Pass the security info to the login modules configured for
+    this security domain using our SecurityAssociationHandler.
+    @return The authenticated Subject if successful.
+    @exception LoginException throw if login fails for any reason.
+    */
+   private LoginContext defaultLogin(Principal principal, Object credential)
+      throws LoginException
+   {
+      /* We use our internal CallbackHandler to provide the security info. A
+      copy must be made to ensure there is a unique handler per active
+      login since there can be multiple active logins.
+      */
+      Object[] securityInfo = {principal, credential};
+      CallbackHandler theHandler = null;
+      try
+      {
+         theHandler = (CallbackHandler) handler.getClass().newInstance();
+         setSecurityInfo.invoke(theHandler, securityInfo);
+      }
+      catch (Throwable e)
+      {
+         if( trace )
+            log.trace("Failed to create/setSecurityInfo on handler", e);
+         LoginException le = new LoginException("Failed to setSecurityInfo on handler");
+         le.initCause(e);
+         throw le;
+      }
+      Subject subject = new Subject();
+      LoginContext lc = null;
+      if( trace )
+         log.trace("defaultLogin, principal="+principal);
+      lc = SubjectActions.createLoginContext(securityDomain, subject, theHandler);
+      lc.login();
+      if( trace )
+         log.trace("defaultLogin, lc="+lc+", subject="+SubjectActions.toString(subject));
+      return lc;
+   }
+
+   /** Validate the cache credential value against the provided credential
+    */
+   private boolean validateCache(DomainInfo info, Object credential,
+      Subject theSubject)
+   {
+      if( trace )
+      {
+         StringBuffer tmp = new StringBuffer("Begin validateCache, info=");
+         tmp.append(info.toString());
+         tmp.append(";credential.class=");
+         if( credential != null )
+         {
+            Class c = credential.getClass();
+            tmp.append(c.getName());
+            tmp.append('@');
+            tmp.append(System.identityHashCode(c));
+         }
+         else
+         {
+            tmp.append("null");
+         }
+         log.trace(tmp.toString());
+      }
+
+      Object subjectCredential = info.credential;
+      boolean isValid = false;
+      // Check for a null credential as can be the case for an anonymous user
+      if( credential == null || subjectCredential == null )
+      {
+         // Both credentials must be null
+         isValid = (credential == null) && (subjectCredential == null);
+      }
+      // See if the credential is assignable to the cache value
+      else if( subjectCredential.getClass().isAssignableFrom(credential.getClass()) )
+      {
+        /* Validate the credential by trying Comparable, char[], byte[],
+         Object[], and finally Object.equals()
+         */
+         if( subjectCredential instanceof Comparable )
+         {
+            Comparable c = (Comparable) subjectCredential;
+            isValid = c.compareTo(credential) == 0;
+         }
+         else if( subjectCredential instanceof char[] )
+         {
+            char[] a1 = (char[]) subjectCredential;
+            char[] a2 = (char[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else if( subjectCredential instanceof byte[] )
+         {
+            byte[] a1 = (byte[]) subjectCredential;
+            byte[] a2 = (byte[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else if( subjectCredential.getClass().isArray() )
+         {
+            Object[] a1 = (Object[]) subjectCredential;
+            Object[] a2 = (Object[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else
+         {
+            isValid = subjectCredential.equals(credential);
+         }
+      }
+      else if( subjectCredential instanceof char[] && credential instanceof String )
+      {
+         char[] a1 = (char[]) subjectCredential;
+         char[] a2 = ((String) credential).toCharArray();
+         isValid = Arrays.equals(a1, a2);
+      }
+      else if( subjectCredential instanceof String && credential instanceof char[] )
+      {
+         char[] a1 = ((String) subjectCredential).toCharArray();
+         char[] a2 = (char[]) credential;
+         isValid = Arrays.equals(a1, a2);         
+      }
+
+      // If the credentials match, set the thread's active Subject
+      if( isValid )
+      {
+         // Copy the current subject into theSubject
+         if( theSubject != null )
+         {
+            SubjectActions.copySubject(info.subject, theSubject, false,this.deepCopySubjectOption);
+         }
+      }
+      if( trace )
+         log.trace("End validateCache, isValid="+isValid);
+
+      return isValid;
+   }
+ 
+   /** An accessor method that synchronizes access on the domainCache
+    to avoid a race condition that can occur when the cache entry expires
+    in the presence of multi-threaded access. The allowRefresh flag should
+    be true for authentication accesses and false for other accesses.
+    Previously the other accesses included authorization and caller principal
+    mapping. Now the only use of the 
+
+    @param principal - the caller identity whose cached credentials are to
+    be accessed.
+    @param allowRefresh - a flag indicating if the cache access should flush
+    any expired entries.
+    */
+   private DomainInfo getCacheInfo(Principal principal, boolean allowRefresh)
+   {
+      if( domainCache == null )
+         return null;
+
+      DomainInfo cacheInfo = null;
+      synchronized( domainCache )
+      {
+          if( allowRefresh == true )
+            cacheInfo = (DomainInfo) domainCache.get(principal);
+          else
+            cacheInfo = (DomainInfo) domainCache.peek(principal);
+         if( cacheInfo != null )
+            cacheInfo.acquire();
+      }
+      return cacheInfo;
+   }
+
+   private Subject updateCache(LoginContext lc, Subject subject,
+      Principal principal, Object credential)
+   {
+      // If we don't have a cache there is nothing to update
+      if( domainCache == null )
+         return subject;
+
+      long lifetime = 0;
+      if( domainCache instanceof TimedCachePolicy )
+      {
+         TimedCachePolicy cache = (TimedCachePolicy) domainCache;
+         lifetime = cache.getDefaultLifetime();
+      }
+      DomainInfo info = new DomainInfo(lifetime);
+      info.loginCtx = lc;
+      info.subject = new Subject();
+      SubjectActions.copySubject(subject, info.subject, true, this.deepCopySubjectOption);
+      info.credential = credential;
+
+      if( trace )
+      {
+         log.trace("updateCache, inputSubject="+SubjectActions.toString(subject)
+            +", cacheSubject="+SubjectActions.toString(info.subject));
+      }
+
+     /* Get the Subject callerPrincipal by looking for a Group called
+        'CallerPrincipal'
+      */
+      Set subjectGroups = subject.getPrincipals(Group.class);
+      Iterator iter = subjectGroups.iterator();
+      while( iter.hasNext() )
+      {
+         Group grp = (Group) iter.next();
+         String name = grp.getName();
+         if( name.equals("CallerPrincipal") )
+         {
+            Enumeration members = grp.members();
+            if( members.hasMoreElements() )
+               info.callerPrincipal = (Principal) members.nextElement();
+         }
+      }
+      
+     /* Handle null principals with no callerPrincipal. This is an indication
+        of an user that has not provided any authentication info, but
+        has been authenticated by the domain login module stack. Here we look
+        for the first non-Group Principal and use that.
+      */
+      if( principal == null && info.callerPrincipal == null )
+      {
+         Set subjectPrincipals = subject.getPrincipals(Principal.class);
+         iter = subjectPrincipals.iterator();
+         while( iter.hasNext() )
+         {
+            Principal p = (Principal) iter.next();
+            if( (p instanceof Group) == false )
+               info.callerPrincipal = p;
+         }
+      }
+
+     /* If the user already exists another login is active. Currently
+        only one is allowed so remove the old and insert the new. Synchronize
+        on the domainCache to ensure the removal and addition are an atomic
+        operation so that getCacheInfo cannot see stale data.
+      */
+      synchronized( domainCache )
+      {
+         if( domainCache.peek(principal) != null )
+            domainCache.remove(principal);
+         domainCache.insert(principal, info);
+         if( trace )
+            log.trace("Inserted cache info: "+info);
+      }
+      return info.subject;
+   } 
+}

Added: trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,806 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.security.Principal;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.List;
+import java.util.Map;
+import java.util.Iterator;
+import java.beans.PropertyEditorManager;
+ 
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.spi.ObjectFactory;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.Subject;
+import javax.security.jacc.PolicyContext;
+
+import org.jboss.logging.Logger;  
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.AuthorizationManager;
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.SecurityProxyFactory;
+import org.jboss.security.SecurityDomain;
+import org.jboss.security.auth.callback.CallbackHandlerPolicyContextHandler;
+import org.jboss.security.jacc.SubjectPolicyContextHandler;
+import org.jboss.security.propertyeditor.PrincipalEditor;
+import org.jboss.security.propertyeditor.SecurityDomainEditor;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.util.CachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+/**
+ * This is a JMX service which manages JAAS based SecurityManagers.
+ * JAAS SecurityManagers are responsible for validating credentials
+ * associated with principals. The service defaults to the
+ * org.jboss.security.plugins.JaasSecurityManager implementation but
+ * this can be changed via the securityManagerClass property.
+ *
+ * @see JaasSecurityManager
+ * @see org.jboss.security.SubjectSecurityManager
+ * 
+ * @author <a href="on at ibis.odessa.ua">Oleg Nitz</a>
+ * @author <a href="rickard at telkel.com">Rickard Oberg</a>
+ * @author <a href="mailto:Scott.Stark at jboss.org">Scott Stark</a>
+ * @version $Revision: 62903 $
+ */
+public class JaasSecurityManagerService
+   extends ServiceMBeanSupport
+   implements JaasSecurityManagerServiceMBean
+{
+   private static final String SECURITY_MGR_PATH = "java:/jaas";
+   private static final String DEFAULT_CACHE_POLICY_PATH = "java:/timedCacheFactory";
+   /** The log4j interface */
+   private static Logger log;
+   /** The class that provides the security manager implementation */
+   private static String securityMgrClassName = "org.jboss.security.plugins.JaasSecurityManager";
+   /** The loaded securityMgrClassName */
+   private static Class securityMgrClass = JaasSecurityManager.class;
+   /** The JAAS CallbackHandler interface implementation to use */
+   private static String callbackHandlerClassName = "org.jboss.security.auth.callback.SecurityAssociationHandler";
+   private static Class callbackHandlerClass = org.jboss.security.auth.callback.SecurityAssociationHandler.class;
+
+   /** The location of the security credential cache policy. This is first treated
+    as a ObjectFactory location that is capable of returning CachePolicy instances
+    on a per security domain basis by appending a '/security-domain-name' string
+    to this name when looking up the CachePolicy for a domain. If this fails then
+    the location is treated as a single CachePolicy for all security domains.
+    */
+   private static String cacheJndiName = DEFAULT_CACHE_POLICY_PATH;
+   private static int defaultCacheTimeout = 30*60;
+   private static int defaultCacheResolution = 60;
+   /** The class that provides the SecurityProxyFactory implementation */
+   private static String securityProxyFactoryClassName = "org.jboss.security.SubjectSecurityProxyFactory";
+   private static Class securityProxyFactoryClass = org.jboss.security.SubjectSecurityProxyFactory.class;
+   /** A mapping from security domain name to a SecurityDomainContext object */
+   private static ConcurrentHashMap securityDomainCtxMap = new ConcurrentHashMap();
+   private static NameParser parser;
+   /** A flag indicating if the SecurityAssociation.setServer should be called */
+   private boolean serverMode = true;
+   /** A flag indicating if the Deep Copy of Subject Sets should be enabled in the security managers */
+   private static boolean deepCopySubjectMode = false;
+
+   /** The default unauthenticated principal */
+   private static String defaultUnauthenticatedPrincipal = "Unauthenticated Principal";  
+
+   static
+   {
+      // Get a log interface, required for some statics below
+      // can not use instance field inherited from ServiceMBeanSupport
+      log = Logger.getLogger(JaasSecurityManagerService.class);
+
+   }
+
+   /** The constructor does nothing as the security manager is created
+    on each lookup into java:/jaas/xxx. This is also why all variables
+    in this class are static.
+    */
+   public JaasSecurityManagerService()
+   {
+   }
+
+   public boolean getServerMode()
+   {
+      return serverMode;
+   }
+   public void setServerMode(boolean mode)
+   {
+      this.serverMode = mode;
+   }
+
+   public String getSecurityManagerClassName()
+   {
+      return securityMgrClassName;
+   }
+   public void setSecurityManagerClassName(String className)
+      throws ClassNotFoundException, ClassCastException
+   {
+      securityMgrClassName = className;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      securityMgrClass = loader.loadClass(securityMgrClassName);
+      if( AuthenticationManager.class.isAssignableFrom(securityMgrClass) == false )
+         throw new ClassCastException(securityMgrClass+" does not implement "+AuthenticationManager.class);
+   }
+   public String getSecurityProxyFactoryClassName()
+   {
+      return securityProxyFactoryClassName;
+   }
+   public void setSecurityProxyFactoryClassName(String className)
+      throws ClassNotFoundException
+   {
+      securityProxyFactoryClassName = className;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      securityProxyFactoryClass = loader.loadClass(securityProxyFactoryClassName);
+   } 
+
+   /** Get the default CallbackHandler implementation class name
+    *
+    * @return The fully qualified classname of the
+    */
+   public String getCallbackHandlerClassName()
+   {
+      return JaasSecurityManagerService.callbackHandlerClassName;
+   }
+   /** Set the default CallbackHandler implementation class name
+    * @see javax.security.auth.callback.CallbackHandler
+    */
+   public void setCallbackHandlerClassName(String className)
+      throws ClassNotFoundException
+   {
+      callbackHandlerClassName = className;
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      callbackHandlerClass = loader.loadClass(callbackHandlerClassName);
+   }
+
+   /** Get the jndi name under which the authentication cache policy is found
+    */
+   public String getAuthenticationCacheJndiName()
+   {
+      return cacheJndiName;
+   }
+   /** Set the jndi name under which the authentication cache policy is found
+    */
+   public void setAuthenticationCacheJndiName(String jndiName)
+   {
+      cacheJndiName = jndiName;
+   }
+   /** Get the default timed cache policy timeout.
+    @return the default cache timeout in seconds.
+    */
+   public int getDefaultCacheTimeout()
+   {
+      return defaultCacheTimeout;
+   }
+   /** Set the default timed cache policy timeout. This has no affect if the
+    AuthenticationCacheJndiName has been changed from the default value.
+    @param timeoutInSecs - the cache timeout in seconds.
+    */
+   public void setDefaultCacheTimeout(int timeoutInSecs)
+   {
+      defaultCacheTimeout = timeoutInSecs;
+   }
+   /** Get the default timed cache policy resolution.
+    */
+   public int getDefaultCacheResolution()
+   {
+      return defaultCacheResolution;
+   }
+   /** Set the default timed cache policy resolution. This has no affect if the
+    AuthenticationCacheJndiName has been changed from the default value.
+    @param resInSecs - resolution of timeouts in seconds.
+    */
+   public void setDefaultCacheResolution(int resInSecs)
+   {
+      defaultCacheResolution = resInSecs;
+   }
+
+   /**
+    * @see JaasSecurityManagerServiceMBean#getDeepCopySubjectMode()
+    */
+   public boolean getDeepCopySubjectMode()
+   { 
+      return deepCopySubjectMode;
+   }
+
+   /**
+    * @see JaasSecurityManagerServiceMBean#getDeepCopySubjectMode() 
+    */
+   public void setDeepCopySubjectMode(boolean flag)
+   {  
+      log.debug("setDeepCopySubjectMode="+flag);
+      deepCopySubjectMode = flag;
+      //Update the security managers if already present
+      if(securityDomainCtxMap.isEmpty() == false)
+      {
+         Iterator iter = securityDomainCtxMap.keySet().iterator();
+         while(iter.hasNext())
+         {
+            String securityDomainName = (String)iter.next();
+            SecurityDomainContext sdc = (SecurityDomainContext)securityDomainCtxMap.get(securityDomainName);
+            setDeepCopySubjectOption(sdc.securityMgr, flag);
+         }
+      }
+   }
+
+   /** Set the indicated security domain cache timeout. This only has an
+    effect if the security domain is using the default jboss TimedCachePolicy
+    implementation.
+
+    @param securityDomain the name of the security domain cache
+    @param timeoutInSecs - the cache timeout in seconds.
+    @param resInSecs - resolution of timeouts in seconds.
+    */
+   public void setCacheTimeout(String securityDomain, int timeoutInSecs, int resInSecs)
+   {
+      CachePolicy cache = getCachePolicy(securityDomain);
+      if( cache != null && cache instanceof TimedCachePolicy )
+      {
+         TimedCachePolicy tcp = (TimedCachePolicy) cache;
+         synchronized( tcp )
+         {
+            tcp.setDefaultLifetime(timeoutInSecs);
+            tcp.setResolution(resInSecs);
+         }
+      }
+      else
+      {
+         log.warn("Failed to find cache policy for securityDomain='"
+            + securityDomain + "'");
+      }
+   } 
+
+   /** flush the cache policy for the indicated security domain if one exists.
+    * @param securityDomain the name of the security domain cache
+    */
+   public void flushAuthenticationCache(String securityDomain)
+   {
+      CachePolicy cache = getCachePolicy(securityDomain);
+      if( cache != null )
+      {
+         cache.flush();
+      }
+      else
+      {
+         log.warn("Failed to find cache policy for securityDomain='"
+            + securityDomain + "'");
+      }
+   }
+
+   /** Flush a principal's authentication cache entry associated with the
+    * given securityDomain.
+    *
+    * @param securityDomain the name of the security domain cache
+    * @param user the principal of the user to flush
+    */
+   public void flushAuthenticationCache(String securityDomain, Principal user)
+   {
+      CachePolicy cache = getCachePolicy(securityDomain);
+      if( cache != null )
+      {
+         cache.remove(user);
+      }
+      else
+      {
+         log.warn("Failed to find cache policy for securityDomain='"
+            + securityDomain + "'");
+      }
+   }
+
+   /** Return the active principals in the indicated security domain auth cache.
+    * @param securityDomain the name of the security to lookup the cache for
+    * @return List<Principal> of active keys found in the auth cache if
+    *    the cache exists and is accessible, null otherwise.
+    */
+   public List getAuthenticationCachePrincipals(String securityDomain)
+   {
+      CachePolicy cache = getCachePolicy(securityDomain);
+      List validPrincipals = null;
+      if( cache instanceof TimedCachePolicy )
+      {
+         TimedCachePolicy tcache = (TimedCachePolicy) cache;
+         validPrincipals = tcache.getValidKeys();
+      }
+      return validPrincipals;
+   }
+
+// Begin SecurityManagerMBean interface methods
+   public boolean isValid(String securityDomain, Principal principal, Object credential)
+   {
+      boolean isValid = false;
+      try
+      {
+         SecurityDomainContext sdc = lookupSecurityDomain(securityDomain);
+         isValid = sdc.getSecurityManager().isValid(principal, credential, null);
+      }
+      catch(NamingException e)
+      {
+         log.debug("isValid("+securityDomain+") failed", e);
+      }
+      return isValid;
+   }
+
+   public Principal getPrincipal(String securityDomain, Principal principal)
+   {
+      Principal realmPrincipal = null;
+      try
+      {
+         SecurityDomainContext sdc = lookupSecurityDomain(securityDomain);
+         realmPrincipal = sdc.getRealmMapping().getPrincipal(principal);
+      }
+      catch(NamingException e)
+      {
+         log.debug("getPrincipal("+securityDomain+") failed", e);
+      }
+      return realmPrincipal;
+   }
+
+    public boolean doesUserHaveRole(String securityDomain, Principal principal,
+       Object credential, Set roles)
+    {
+       boolean doesUserHaveRole = false;
+       try
+       {
+          SecurityDomainContext sdc = lookupSecurityDomain(securityDomain);
+          // Must first validate the user
+          Subject subject = new Subject();
+          boolean isValid = sdc.getSecurityManager().isValid(principal, credential, subject);
+          if( isValid )
+          {
+             // Now can query if the authenticated Subject has the role
+             SubjectActions.pushSubjectContext(principal, credential, subject,
+                   sdc.getSecurityManager().getSecurityDomain());
+             doesUserHaveRole = sdc.getRealmMapping().doesUserHaveRole(principal, roles);
+             SubjectActions.popSubjectContext();
+          }
+       }
+       catch(NamingException e)
+       {
+          log.debug("doesUserHaveRole("+securityDomain+") failed", e);
+       }
+       return doesUserHaveRole;
+    }
+
+    public Set getUserRoles(String securityDomain, Principal principal, Object credential)
+    {
+       Set userRoles = null;
+       try
+       {
+          SecurityDomainContext sdc = lookupSecurityDomain(securityDomain);
+          // Must first validate the user
+          Subject subject = new Subject();
+          boolean isValid = sdc.getSecurityManager().isValid(principal, credential, subject);
+          // Now can query if the authenticated Subject has the role
+          if( isValid )
+          {
+            SubjectActions.pushSubjectContext(principal, credential, subject,
+                  sdc.getSecurityManager().getSecurityDomain() );
+            userRoles = sdc.getRealmMapping().getUserRoles(principal);
+             SubjectActions.popSubjectContext();
+          }
+       }
+       catch(NamingException e)
+       {
+          log.debug("getUserRoles("+securityDomain+") failed", e);
+       }
+       return userRoles;
+    }
+// End SecurityManagerMBean interface methods
+
+   protected void startService() throws Exception
+   {
+      // use thread-local principal and credential propagation
+      if (serverMode)
+         SecurityAssociation.setServer();
+
+      // Register the default active Subject PolicyContextHandler
+      SubjectPolicyContextHandler handler = new SubjectPolicyContextHandler();
+      PolicyContext.registerHandler(SecurityConstants.SUBJECT_CONTEXT_KEY,
+         handler, true);
+      // Register the JAAS CallbackHandler JACC PolicyContextHandlers
+      CallbackHandlerPolicyContextHandler chandler = new CallbackHandlerPolicyContextHandler();
+      PolicyContext.registerHandler(CallbackHandlerPolicyContextHandler.CALLBACK_HANDLER_KEY,
+         chandler, false);
+
+      Context ctx = new InitialContext();
+      parser = ctx.getNameParser("");
+
+      /* Create a mapping from the java:/jaas context to a SecurityDomainObjectFactory
+       so that any lookup against java:/jaas/domain returns an instance of our
+       security manager class.
+      */
+      RefAddr refAddr = new StringRefAddr("nns", "JSM");
+      String factoryName = SecurityDomainObjectFactory.class.getName();
+      Reference ref = new Reference("javax.naming.Context", refAddr, factoryName, null);
+      ctx.rebind(SECURITY_MGR_PATH, ref);
+      log.debug("securityMgrCtxPath="+SECURITY_MGR_PATH);
+
+      refAddr = new StringRefAddr("nns", "JSMCachePolicy");
+      factoryName = DefaultCacheObjectFactory.class.getName();
+      ref = new Reference("javax.naming.Context", refAddr, factoryName, null);
+      ctx.rebind(DEFAULT_CACHE_POLICY_PATH, ref);
+      log.debug("cachePolicyCtxPath="+cacheJndiName);
+
+      // Bind the default SecurityProxyFactory instance under java:/SecurityProxyFactory
+      SecurityProxyFactory proxyFactory = (SecurityProxyFactory) securityProxyFactoryClass.newInstance();
+      ctx.bind("java:/SecurityProxyFactory", proxyFactory);
+      log.debug("SecurityProxyFactory="+proxyFactory);
+
+      // Register the Principal property editor
+      PropertyEditorManager.registerEditor(Principal.class, PrincipalEditor.class);
+      PropertyEditorManager.registerEditor(SecurityDomain.class, SecurityDomainEditor.class);
+      log.debug("Registered PrincipalEditor, SecurityDomainEditor");
+
+      log.debug("ServerMode="+this.serverMode);
+      log.debug("SecurityMgrClass="+JaasSecurityManagerService.securityMgrClass);
+      log.debug("CallbackHandlerClass="+JaasSecurityManagerService.callbackHandlerClass);
+   }
+
+   protected void stopService() throws Exception
+   {
+      InitialContext ic = new InitialContext();
+
+      try
+      {
+         ic.unbind(SECURITY_MGR_PATH);
+      }
+      catch(CommunicationException e)
+      {
+         // Do nothing, the naming services is already stopped
+      }
+      finally
+      {
+         ic.close();
+      }
+   }
+
+   /** Register a SecurityDomain implmentation. This is synchronized to ensure
+    * that the binding of the security domain and cache population is atomic.
+    * @param securityDomain the name of the security domain
+    * @param instance the SecurityDomain instance to bind
+    */
+   public synchronized void registerSecurityDomain(String securityDomain, SecurityDomain instance)
+   {
+      log.debug("Added "+securityDomain+", "+instance+" to map");
+      CachePolicy authCache = lookupCachePolicy(securityDomain);
+      
+      SecurityDomainContext sdc = new SecurityDomainContext(instance, authCache);
+      sdc.setAuthorizationManager(AuthorizationManagerService.newAuthorizationManager(securityDomain));
+      securityDomainCtxMap.put(securityDomain, sdc);
+      // See if the security mgr supports an externalized cache policy
+      setSecurityDomainCache(instance, authCache);
+   }
+
+   /** Access the CachePolicy for the securityDomain.
+    * @param securityDomain the name of the security domain
+    * @return The CachePolicy if found, null otherwise.
+    */
+   private static CachePolicy getCachePolicy(String securityDomain)
+   {
+      if( securityDomain.startsWith(SECURITY_MGR_PATH) )
+         securityDomain = securityDomain.substring(SECURITY_MGR_PATH.length()+1);
+      CachePolicy cache = null;
+      try
+      {
+         SecurityDomainContext sdc = lookupSecurityDomain(securityDomain);
+         if( sdc != null )
+            cache = sdc.getAuthenticationCache();
+      }
+      catch(NamingException e)
+      {
+         log.debug("getCachePolicy("+securityDomain+") failure", e);
+      }
+      return cache;
+   }
+
+   /** Lookup the authentication CachePolicy object for a security domain. This
+    method first treats the cacheJndiName as a ObjectFactory location that is
+    capable of returning CachePolicy instances on a per security domain basis
+    by appending a '/security-domain-name' string to the cacheJndiName when
+    looking up the CachePolicy for a domain. If this fails then the cacheJndiName
+    location is treated as a single CachePolicy for all security domains.
+    */
+   static CachePolicy lookupCachePolicy(String securityDomain)
+   {
+      CachePolicy authCache = null;
+      String domainCachePath = cacheJndiName + '/' + securityDomain;
+      try
+      {
+         InitialContext iniCtx = new InitialContext();
+         authCache = (CachePolicy) iniCtx.lookup(domainCachePath);
+      }
+      catch(Exception e)
+      {
+         // Failed, treat the cacheJndiName name as a global CachePolicy binding
+         try
+         {
+            InitialContext iniCtx = new InitialContext();
+            authCache = (CachePolicy) iniCtx.lookup(cacheJndiName);
+         }
+         catch(Exception e2)
+         {
+            log.warn("Failed to locate auth CachePolicy at: "+cacheJndiName
+               + " for securityDomain="+securityDomain);
+         }
+      }
+      return authCache;
+   }
+
+   /** Use reflection to attempt to set the authentication cache on the
+    * securityMgr argument.
+    * @param securityMgr the security manager
+    * @param cachePolicy the cache policy implementation
+    */
+   private static void setSecurityDomainCache(AuthenticationManager securityMgr,
+      CachePolicy cachePolicy)
+   {
+      try
+      {
+         Class[] setCachePolicyTypes = {CachePolicy.class};
+         Method m = securityMgrClass.getMethod("setCachePolicy", setCachePolicyTypes);
+         Object[] setCachePolicyArgs = {cachePolicy};
+         m.invoke(securityMgr, setCachePolicyArgs);
+         log.debug("setCachePolicy, c="+setCachePolicyArgs[0]);
+      }
+      catch(Exception e2)
+      {    
+         if(log.isTraceEnabled())
+            log.trace("Optional setCachePolicy failed" + e2.getLocalizedMessage());
+      }
+   }
+
+   /** Use reflection to attempt to set the DeepCopySubject on the
+    * securityMgr argument.  
+    * @param securityMgr the security manager
+    * @param flag deep copy subject option
+    */
+   private static void setDeepCopySubjectOption(AuthenticationManager securityMgr,
+      boolean flag)
+   { 
+      Boolean bValue = flag ? Boolean.TRUE : Boolean.FALSE;
+      try
+      {
+         Class[] setDeepCopySubjTypes = {Boolean.class};
+         Method m = securityMgrClass.getMethod("setDeepCopySubjectOption", setDeepCopySubjTypes);
+         Object[] setDeepCopySubjectOptionArgs = {bValue};
+         m.invoke(securityMgr, setDeepCopySubjectOptionArgs);
+         log.debug("setDeepCopySubjectOption, c="+setDeepCopySubjectOptionArgs[0]);
+      }
+      catch(Exception e2)
+      {   // No setDeepCopySubjectOption support, this is ok
+         log.debug("setDeepCopySubjectOption failed", e2);
+      }
+   }
+
+   /** Lookup or create the SecurityDomainContext for securityDomain.
+    * @param securityDomain
+    * @return the SecurityDomainContext for securityDomain
+    * @throws NamingException
+    */
+   private synchronized static SecurityDomainContext lookupSecurityDomain(String securityDomain)
+         throws NamingException
+   {
+      SecurityDomainContext securityDomainCtx = (SecurityDomainContext) securityDomainCtxMap.get(securityDomain);
+      if( securityDomainCtx == null )
+      {
+         securityDomainCtx = newSecurityDomainCtx(securityDomain);
+         securityDomainCtxMap.put(securityDomain, securityDomainCtx);
+         log.debug("Added "+securityDomain+", "+securityDomainCtx+" to map");
+      }
+      return securityDomainCtx;
+   }
+
+   /** Create a new SecurityDomainContext for securityDomain. This is
+    * synchronized to ensure that the creation and setting of the domain
+    * cache are atomic.
+    * @param securityDomain
+    * @return the SecurityDomainContext for securityDomain
+    * @throws NamingException
+    */
+   private synchronized static SecurityDomainContext newSecurityDomainCtx(String securityDomain)
+      throws NamingException
+   {
+      SecurityDomainContext sdc = null;
+      try
+      {
+         // Create instance of securityMgrClass
+         Class[] parameterTypes = {String.class, CallbackHandler.class};
+         Constructor ctor = securityMgrClass.getConstructor(parameterTypes);
+         CallbackHandler handler = (CallbackHandler) callbackHandlerClass.newInstance();
+         Object[] args = {securityDomain, handler};
+         AuthenticationManager securityMgr = (AuthenticationManager) ctor.newInstance(args);
+         log.debug("Created securityMgr="+securityMgr);
+         CachePolicy cachePolicy = lookupCachePolicy(securityDomain); 
+         sdc = new SecurityDomainContext(securityMgr, cachePolicy);
+         // See if the security mgr supports an externalized cache policy
+         setSecurityDomainCache(securityMgr, cachePolicy);
+         if(deepCopySubjectMode)
+            setDeepCopySubjectOption(securityMgr, true); 
+         //Set the Authorization Manager 
+         AuthorizationManager am = AuthorizationManagerService.newAuthorizationManager(securityDomain);
+         sdc.setAuthorizationManager(am);  
+      }
+      catch(Exception e2)
+      {
+         String msg = "Failed to create sec mgr('"+securityDomain+"'), securityMgrClass="
+            +securityMgrClass +", callbackHandlerClass="
+            +callbackHandlerClass;
+         NamingException ne = new NamingException(msg);
+         ne.setRootCause(e2);
+         throw ne;
+      }
+      return sdc;
+   } 
+   
+   /**
+    * Get the default unauthenticated principal.
+    * @return The principal name
+    */
+   public String getDefaultUnauthenticatedPrincipal()
+   {
+      return defaultUnauthenticatedPrincipal;
+   }
+
+   /**
+    * Set the default unauthenticated principal.
+    * @param principal The principal name
+    */
+   public void setDefaultUnauthenticatedPrincipal(String principal)
+   {
+      defaultUnauthenticatedPrincipal = principal;
+   }
+
+   // java:/jaas context ObjectFactory implementation
+
+   public static class SecurityDomainObjectFactory
+      implements InvocationHandler, ObjectFactory
+   {
+      /** Object factory implementation. This method returns a Context proxy
+       that is only able to handle a lookup operation for an atomic name of
+       a security domain.
+      */
+      public Object getObjectInstance(Object obj, Name name, Context nameCtx,
+         Hashtable environment)
+         throws Exception
+      {
+         ClassLoader loader = SubjectActions.getContextClassLoader();
+         Class[] interfaces = {Context.class};
+         Context ctx = (Context) Proxy.newProxyInstance(loader, interfaces, this);
+         return ctx;
+      }
+
+
+      /** This is the InvocationHandler callback for the Context interface that
+       was created by out getObjectInstance() method. We handle the java:/jaas/domain
+       level operations here.
+       */
+      public Object invoke(Object obj, Method method, Object[] args) throws Throwable
+      {
+         String methodName = method.getName();
+         if( methodName.equals("toString") == true )
+            return SECURITY_MGR_PATH + " Context proxy";
+         if( methodName.equals("list") == true )
+            return new DomainEnumeration(securityDomainCtxMap.keys(), securityDomainCtxMap);
+
+         if( methodName.equals("lookup") == false )
+            throw new OperationNotSupportedException("Only lookup is supported, op="+method);
+         String securityDomain = null;
+         Name name = null;
+         if( args[0] instanceof String )
+            name = parser.parse((String) args[0]);
+         else
+           name = (Name)args[0];
+         securityDomain = name.get(0);
+         SecurityDomainContext securityDomainCtx = lookupSecurityDomain(securityDomain);
+         Object binding = securityDomainCtx.getSecurityManager();
+         // Look for requests against the security domain context
+         if( name.size() == 2 )
+         {
+            String request = name.get(1);
+            binding = securityDomainCtx.lookup(request);
+         }
+         return binding;
+      }
+   }
+   static class DomainEnumeration implements NamingEnumeration
+   {
+      Enumeration domains;
+      Map ctxMap;
+      DomainEnumeration(Enumeration domains, Map ctxMap)
+      {
+         this.domains = domains;
+         this.ctxMap = ctxMap;
+      }
+
+      public void close()
+      {
+      }
+      public boolean hasMoreElements()
+      {
+         return domains.hasMoreElements();
+      }
+      public boolean hasMore()
+      {
+         return domains.hasMoreElements();
+      }
+      public Object next()
+      {
+         String name = (String) domains.nextElement();
+         Object value = ctxMap.get(name);
+         String className = value.getClass().getName();
+         NameClassPair pair = new NameClassPair(name, className);
+         return pair;
+      }
+      public Object nextElement()
+      {
+         return domains.nextElement();
+      }
+   }
+
+   /** java:/timedCacheFactory ObjectFactory implementation
+    */
+   public static class DefaultCacheObjectFactory implements InvocationHandler, ObjectFactory
+   {
+      /** Object factory implementation. This method returns a Context proxy
+       that is only able to handle a lookup operation for an atomic name of
+       a security domain.
+      */
+      public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment)
+         throws Exception
+      {
+         ClassLoader loader = Thread.currentThread().getContextClassLoader();
+         Class[] interfaces = {Context.class};
+         Context ctx = (Context) Proxy.newProxyInstance(loader, interfaces, this);
+         return ctx;
+      }
+      /** This is the InvocationHandler callback for the Context interface that
+       was created by out getObjectInstance() method. All this does is create
+       a new TimedCache instance.
+       */
+      public Object invoke(Object obj, Method method, Object[] args) throws Throwable
+      {
+         TimedCachePolicy cachePolicy = new TimedCachePolicy(defaultCacheTimeout,
+            true, defaultCacheResolution);
+         cachePolicy.create();
+         cachePolicy.start();
+         return cachePolicy;
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,195 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.security.Principal;
+import java.util.List;
+import javax.management.ObjectName;
+
+import org.jboss.mx.util.ObjectNameFactory;
+import org.jboss.security.SecurityDomain;
+import org.jboss.system.ServiceMBean;
+
+/**
+ * The management interface for the JaasSecurityManagerService mbean.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 44179 $
+ */
+public interface JaasSecurityManagerServiceMBean
+   extends ServiceMBean, SecurityManagerMBean
+{
+   ObjectName OBJECT_NAME = ObjectNameFactory.create("jboss.security:service=JaasSecurityManager");
+
+   /** A flag indicating if the Deep Copy of Subject Sets should be enabled in the security managers */
+   public boolean getDeepCopySubjectMode();
+   
+   /**
+    * A flag indicating if the Deep Copy of Subject Sets should be enabled in the security managers
+    * 
+    * @param flag
+    */
+   public void setDeepCopySubjectMode(boolean flag);
+   
+   /**
+    * A flag indicating if the SecurityAssociation.setServer should be called
+    * on service startup.
+    * @return the SecurityAssociation.setServer flag.
+    */
+   public boolean getServerMode();
+
+   /**
+    * The SecurityAssociation server mode flag.
+    * 
+    * @param flag -  A flag indicating if the SecurityAssociation.setServer
+    * should be called on service startup.
+    */
+   public void setServerMode(boolean flag);
+
+   /**
+    * Get the name of the class that provides the security manager implementation.
+    */
+   String getSecurityManagerClassName();
+   
+   /**
+    * Set the name of the class that provides the security manager implementation.
+    * 
+    * @exception ClassNotFoundException thrown if the className cannot be found
+    * using the thread context class loader.
+    * @exception ClassCastException thrown if the className does not implement the
+    * org.jboss.security.AuthenticationManager interface.
+    */
+   void setSecurityManagerClassName(String className)
+      throws ClassNotFoundException, ClassCastException;
+   
+   /**
+    * Get the name of the class that provides the SecurityProxyFactory implementation.
+    */
+   String getSecurityProxyFactoryClassName();
+   
+   /**
+    * Set the name of the class that provides the SecurityProxyFactory implementation.
+    */
+   void setSecurityProxyFactoryClassName(String className)
+      throws ClassNotFoundException;
+   
+   /** Get the default CallbackHandler implementation class name
+    *
+    * @return The fully qualified classname of the
+    */
+   public String getCallbackHandlerClassName();
+   /** Set the default CallbackHandler implementation class name
+    * @see javax.security.auth.callback.CallbackHandler
+    */
+   public void setCallbackHandlerClassName(String className)
+      throws ClassNotFoundException;
+
+   /**
+    * Get the jndi name under which the authentication CachePolicy implenentation
+    * is found
+    */
+   String getAuthenticationCacheJndiName();
+   
+   /**
+    * Set the location of the security credential cache policy. This is first treated
+    * as a ObjectFactory location that is capable of returning CachePolicy instances
+    * on a per security domain basis by appending a '/security-domain-name' string
+    * to this name when looking up the CachePolicy for a domain. If this fails then
+    * the location is treated as a single CachePolicy for all security domains.
+    * 
+    * @param jndiName the name to the ObjectFactory or CachePolicy binding.
+    */
+   void setAuthenticationCacheJndiName(String jndiName);
+
+   /**
+    * Get the default timed cache policy timeout.
+    * @return the default cache timeout in seconds.
+    */
+   int getDefaultCacheTimeout();
+   
+   /**
+    * Set the default timed cache policy timeout. This has no affect if the
+    * AuthenticationCacheJndiName has been changed from the default value.
+    * @param timeoutInSecs the cache timeout in seconds.
+    */
+   void setDefaultCacheTimeout(int timeoutInSecs);
+   
+   /**
+    * Get the default timed cache policy resolution.
+    */
+   int getDefaultCacheResolution();
+   
+   /**
+    * Set the default timed cache policy resolution. This has no affect if the
+    * AuthenticationCacheJndiName has been changed from the default value.
+    * 
+    * @param resInSecs resolution of timeouts in seconds.
+    */
+   void setDefaultCacheResolution(int resInSecs);
+
+   /** Set the indicated security domain cache timeout. This only has an
+    * effect if the security domain is using the default jboss TimedCachePolicy
+    * implementation.
+     
+    @param securityDomain the name of the security domain cache
+    @param timeoutInSecs - the cache timeout in seconds.
+    @param resInSecs - resolution of timeouts in seconds.
+    */ 
+   public void setCacheTimeout(String securityDomain, int timeoutInSecs, int resInSecs);
+
+   /** Flush the authentication cache associated with the given securityDomain.
+    *
+    * @param securityDomain the name of the security domain cache
+    */
+   void flushAuthenticationCache(String securityDomain);
+
+   /** Flush a principal's authentication cache entry associated with the
+    * given securityDomain.
+    *
+    * @param securityDomain the name of the security domain cache
+    * @param user the principal of the user to flush
+    */
+   void flushAuthenticationCache(String securityDomain, Principal user);
+
+   /** The the list of active Principls for the given security domain
+    * @param securityDomain
+    * @return List<Princpals> of active users, may be null.
+    */
+   List getAuthenticationCachePrincipals(String securityDomain);
+
+   /**
+    * Register a SecurityDomain implmentation
+    */
+   void registerSecurityDomain(String securityDomain, SecurityDomain instance);
+
+   /**
+    * Get the default unauthenticated principal.
+    * @return The principal name
+    */
+   String getDefaultUnauthenticatedPrincipal();
+
+   /**
+    * Set the default unauthenticated principal.
+    * @param principal The principal name
+    */
+   void setDefaultUnauthenticatedPrincipal(String principal);
+}

Added: trunk/security/src/main/org/jboss/security/plugins/SecurityConfig.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/SecurityConfig.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/SecurityConfig.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,157 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+ 
+import java.util.Stack;
+import javax.management.JMException;
+import javax.management.MalformedObjectNameException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.security.auth.login.Configuration;
+
+import org.jboss.system.ServiceMBeanSupport;
+
+/** The SecurityConfigMBean implementation. This class needs the
+ javax.security.auth.AuthPermission("setLoginConfiguration") to install
+ the javax.security.auth.login.Configuration when running with a security
+ manager.
+ 
+ @author Scott.Stark at jboss.org
+ @version $Revision: 58710 $
+ */
+public class SecurityConfig extends ServiceMBeanSupport
+   implements SecurityConfigMBean
+{
+   // Constants -----------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   /** The default Configuration mbean name */
+   private String loginConfigName;
+   /** The stack of Configuration mbeans that are active */
+   private Stack loginConfigStack = new Stack();
+
+   static class ConfigInfo
+   {
+      ObjectName name;
+      Configuration config;
+      ConfigInfo(ObjectName name, Configuration config)
+      {
+         this.name = name;
+         this.config = config;
+      }
+   }
+
+   public SecurityConfig()
+   {
+   }
+   
+   public String getName()
+   {
+      return "SecurityIntialization";
+   }
+
+   /** Get the name of the mbean that provides the default JAAS login configuration 
+    */
+   public String getLoginConfig()
+   {
+      return loginConfigName;
+   }
+
+   /** Set the name of the mbean that provides the default JAAS login configuration 
+    */
+   public void setLoginConfig(String name) throws MalformedObjectNameException
+   {
+      this.loginConfigName = name;
+   }
+
+   /** Start the configuration service by pushing the mbean given by the
+    LoginConfig onto the configuration stack.
+    */
+   public void startService() throws Exception
+   {
+      pushLoginConfig(loginConfigName);
+   }
+
+   /** Start the configuration service by poping the top of the
+    configuration stack.
+    */
+   public void stopService() throws Exception
+   {
+      if( loginConfigStack.empty() == false )
+         popLoginConfig();
+   }
+
+   /** Push an mbean onto the login configuration stack and install its
+    Configuration as the current instance.
+    @see javax.security.auth.login.Configuration
+    */
+   public synchronized void pushLoginConfig(String objectName)
+      throws JMException, MalformedObjectNameException
+   {
+      ObjectName name = new ObjectName(objectName);
+      Configuration prevConfig = null;
+      if( loginConfigStack.empty() == false )
+      {
+         ConfigInfo prevInfo = (ConfigInfo) loginConfigStack.peek();
+         prevConfig = prevInfo.config;
+      }
+
+      ConfigInfo info = installConfig(name, prevConfig);
+      loginConfigStack.push(info);
+   }
+   /** Pop the current mbean from the login configuration stack and install
+    the previous Configuration as the current instance.
+    @see javax.security.auth.login.Configuration
+    */
+   public synchronized void popLoginConfig()
+      throws JMException
+   {
+      ConfigInfo info = (ConfigInfo) loginConfigStack.pop();
+      Configuration prevConfig = null;
+      if( loginConfigStack.empty() == false )
+      {
+         ConfigInfo prevInfo = (ConfigInfo) loginConfigStack.peek();
+         prevConfig = prevInfo.config;
+      }
+
+      installConfig(info.name, prevConfig);
+   }
+
+   /** Obtain the Configuration from the named mbean using its getConfiguration
+    operation and install it as the current Configuration.
+
+    @see Configuration.setConfiguration(javax.security.auth.login.Configuration)
+    */
+   private ConfigInfo installConfig(ObjectName name, Configuration prevConfig)
+      throws JMException
+   {
+      MBeanServer server = super.getServer();
+      Object[] args = {prevConfig};
+      String[] signature = {"javax.security.auth.login.Configuration"};
+      Configuration config = (Configuration) server.invoke(name,
+         "getConfiguration", args, signature);
+      Configuration.setConfiguration(config);
+      ConfigInfo info = new ConfigInfo(name, config);
+      log.debug("Installed JAAS Configuration service="+name+", config="+config);
+      return info;
+   }
+}

Added: trunk/security/src/main/org/jboss/security/plugins/SecurityConfigMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/SecurityConfigMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/SecurityConfigMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,55 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import javax.management.JMException;
+import javax.management.MalformedObjectNameException;
+
+import org.jboss.system.ServiceMBean;
+
+/** A security configuration MBean. This establishes the JAAS and Java2
+ security properties and related configuration.
+
+ @see DefaultLoginConfig
+ @see javax.security.auth.login.Configuration
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 40069 $
+*/
+public interface SecurityConfigMBean extends ServiceMBean
+{
+   /** Get the name of the mbean that provides the default JAAS login configuration */
+   public String getLoginConfig();
+   /** Set the name of the mbean that provides the default JAAS login configuration */
+   public void setLoginConfig(String objectName) throws MalformedObjectNameException;
+   /** Push an mbean onto the login configuration stack and install its
+    Configuration as the current instance.
+    @see javax.security.auth.login.Configuration
+    */
+   public void pushLoginConfig(String objectName) throws JMException, MalformedObjectNameException;
+   /** Pop the current mbean from the login configuration stack and install
+    the previous Configuration as the current instance.
+    @see javax.security.auth.login.Configuration
+    */
+   public void popLoginConfig() throws JMException;
+
+}

Added: trunk/security/src/main/org/jboss/security/plugins/SecurityDomainContext.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/SecurityDomainContext.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/SecurityDomainContext.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,124 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+
+import org.jboss.security.AuthorizationManager;
+import org.jboss.security.RealmMapping;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.SubjectSecurityManager;
+import org.jboss.util.CachePolicy;
+
+/** An encapsulation of the JNDI security context infomation
+ *
+ * @author  Scott.Stark at jboss.org
+ * @author  Anil.Saldhana at jboss.org
+ * @version 
+ */
+public class SecurityDomainContext
+{
+   static final String ACTIVE_SUBJECT = "subject";
+   static final String AUTHENTICATION_MGR = "securityMgr";
+   static final String REALM_MAPPING = "realmMapping";
+   static final String AUTHORIZATION_MGR = "authorizationMgr";
+   static final String AUTH_CACHE = "authenticationCache";
+   static final String DOMAIN_CONTEXT = "domainContext";
+
+   AuthenticationManager securityMgr;
+   AuthorizationManager authorizationMgr;
+   CachePolicy authenticationCache;
+
+   /** Creates new SecurityDomainContextHandler */
+   public SecurityDomainContext(AuthenticationManager securityMgr, 
+         CachePolicy authenticationCache)
+   {
+      this.securityMgr = securityMgr;
+      this.authenticationCache = authenticationCache; 
+   }
+
+   public Object lookup(String name) throws NamingException
+   {
+      Object binding = null;
+      if( name == null || name.length() == 0 )
+         throw new InvalidNameException("name cannot be null or empty");
+
+      if( name.equals(ACTIVE_SUBJECT) )
+         binding = getSubject();
+      else if( name.equals(AUTHENTICATION_MGR) )
+         binding = securityMgr;
+      else if( name.equals(REALM_MAPPING) )
+         binding = getRealmMapping();
+      else if( name.equals(AUTHORIZATION_MGR) )
+         binding = getAuthorizationManager();
+      else if( name.equals(AUTH_CACHE) )
+         binding = authenticationCache;
+      else if( name.equals(DOMAIN_CONTEXT) )
+         binding = this;
+         
+      return binding;
+   }
+   public Subject getSubject()
+   {
+      Subject subject = null;
+      if( securityMgr instanceof SubjectSecurityManager )
+      {
+         subject = ((SubjectSecurityManager)securityMgr).getActiveSubject();
+      }
+      return subject;
+   }
+   public AuthenticationManager getSecurityManager()
+   {
+      return securityMgr;
+   }
+   public RealmMapping getRealmMapping()
+   {
+      RealmMapping realmMapping = null;
+      if(authorizationMgr != null && authorizationMgr instanceof RealmMapping)
+      {
+         realmMapping = (RealmMapping)authorizationMgr;
+      }
+      else
+      if( securityMgr instanceof RealmMapping )
+      {
+         realmMapping = (RealmMapping)securityMgr;
+      }
+      return realmMapping;
+   }
+   
+   public void setAuthorizationManager(AuthorizationManager am)
+   {
+      this.authorizationMgr = am;
+   }
+   
+   public AuthorizationManager getAuthorizationManager()
+   {
+      return authorizationMgr;
+   }
+   
+   public CachePolicy getAuthenticationCache()
+   {
+      return authenticationCache;
+   } 
+}

Added: trunk/security/src/main/org/jboss/security/plugins/SecurityManagerMBean.java
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/SecurityManagerMBean.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/SecurityManagerMBean.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,83 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.plugins;
+
+import java.security.Principal;
+import java.util.Set;
+
+/** An MBean interface that unifies the AuthenticationManager and RealmMapping
+ * security interfaces implemented by a security manager for a given domain
+ * and provides access to this functionality across all domains by including
+ * the security domain name as a method argument.
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public interface SecurityManagerMBean
+{
+
+   /** The isValid method is invoked to see if a user identity and associated
+    credentials as known in the operational environment are valid proof of the
+    user identity.
+    @param securityDomain - the name of the security to use
+    @param principal - the user identity in the operation environment
+    @param credential - the proof of user identity as known in the
+    operation environment
+    @return true if the principal, credential pair is valid, false otherwise.
+   */
+   public boolean isValid(String securityDomain, Principal principal, Object credential);
+
+    /** Map from the operational environment Principal to the application
+     domain principal. This is used by the EJBContext.getCallerPrincipal implentation
+     to map from the authenticated principal to a principal in the application
+     domain.
+    @param principal - the caller principal as known in the operation environment.
+    @return the principal
+    */
+    public Principal getPrincipal(String securityDomain, Principal principal);
+
+    /** Validates the application domain roles to which the operational
+    environment Principal belongs. This may first authenticate the principal
+    as some security manager impls require a preceeding isValid call.
+     @param securityDomain - the name of the security to use
+     @param principal - the user identity in the operation environment
+     @param credential - the proof of user identity as known in the
+    @param roles - Set<Principal> for the application domain roles that the
+     principal is to be validated against.
+    @return true if the principal has at least one of the roles in the roles set,
+        false otherwise.
+     */
+    public boolean doesUserHaveRole(String securityDomain, Principal principal,
+       Object credential, Set roles);
+
+    /** Return the set of domain roles the principal has been assigned.
+     This may first authenticate the principal as some security manager impls
+     require a preceeding isValid call.
+     @param securityDomain - the name of the security to use
+     @param principal - the user identity in the operation environment
+     @param credential - the proof of user identity as known in the
+    @return The Set<Principal> for the application domain roles that the
+     principal has been assigned.
+     */
+    public Set getUserRoles(String securityDomain, Principal principal,
+       Object credential);
+}

Added: trunk/security/src/main/org/jboss/security/plugins/package.html
===================================================================
--- trunk/security/src/main/org/jboss/security/plugins/package.html	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/plugins/package.html	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,3 @@
+<body>
+Security plugins have moved to the jbosssx cvs module.
+</body>

Added: trunk/security/src/main/org/jboss/security/propertyeditor/PrincipalEditor.java
===================================================================
--- trunk/security/src/main/org/jboss/security/propertyeditor/PrincipalEditor.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/propertyeditor/PrincipalEditor.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,55 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.propertyeditor;
+
+import java.beans.PropertyEditorSupport;
+import java.security.Principal;
+
+import org.jboss.security.SimplePrincipal;
+
+/** A property editor for java.security.Principals that uses the
+ * org.jboss.security.SimplePrincipal
+ *
+ * @version <tt>$Revision: 37459 $</tt>
+ * @author Scott.Stark at jboss.org
+ */
+public class PrincipalEditor
+   extends PropertyEditorSupport
+{
+   /** Build a SimplePrincipal
+    * @param text, the name of the Principal
+    */
+   public void setAsText(final String text)
+   {
+      SimplePrincipal principal = new SimplePrincipal(text);
+      setValue(principal);
+   }
+
+   /**
+    * @return the name of the Principal
+    */
+   public String getAsText()
+   {
+      Principal principal = (Principal) getValue();
+      return principal.getName();
+   }
+}

Added: trunk/security/src/main/org/jboss/security/propertyeditor/SecurityDomainEditor.java
===================================================================
--- trunk/security/src/main/org/jboss/security/propertyeditor/SecurityDomainEditor.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/propertyeditor/SecurityDomainEditor.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,203 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.propertyeditor;
+
+import java.beans.PropertyEditorSupport;
+import java.security.KeyStore;
+import java.security.Principal;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.InitialContext;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.security.auth.Subject;
+
+import org.jboss.security.SecurityDomain;
+import org.jboss.logging.Logger;
+
+/** A property editor for org.jboss.security.SecurityDomain types. This editor
+ * transforms a jndi name string to a SecurityDomain by looking up the binding.
+ * The only unusual aspect of this editor is that the jndi name is usually of
+ * the form java:/jaas/xxx and the java:/jaas context is a dynamic ObjectFactory
+ * that will create a binding for any xxx. If there is an attempt to lookup a
+ * binding before it has been created by the underlying service that provides
+ * the SecurityDomain, the lookup will return the default security service
+ * which typically does not implement SecurityDomain. In this case, the editor
+ * will create a proxy that delays the lookup of the SecurityDomain until the
+ * first method invocation against the proxy.
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 56669 $
+ */
+public class SecurityDomainEditor
+   extends PropertyEditorSupport
+{
+   private static Logger log = Logger.getLogger(SecurityDomainEditor.class);
+   private String domainName;
+
+   /** Get the SecurityDomain from the text which is the jndi name of the
+    * SecurityDomain binding. This may have to create a proxy if the current
+    * value of the binding is not a SecurityDomain.
+    * @param text - the name of the Principal
+    */
+   public void setAsText(final String text)
+   {
+      this.domainName = text;
+      try
+      {
+         InitialContext ctx = new InitialContext();
+         Object ref = ctx.lookup(text);
+         SecurityDomain domain = null;
+         if( ref instanceof SecurityDomain )
+         {
+            domain = (SecurityDomain) ref;
+         }
+         else
+         {
+            // Create a proxy to delay the lookup until needed
+            domain = new SecurityDomainProxy(domainName);
+         }
+         setValue(domain);
+      }
+      catch(Exception e)
+      {
+         log.error("Failed to lookup SecurityDomain, "+domainName, e);
+      }
+   }
+
+   /** Return the original security domain jndi name since we cannot get
+    * this back from the SecurityDomain itself.
+    * @return
+    */ 
+   public String getAsText()
+   {
+      return domainName;
+   }
+
+   /** A proxy that delays the lookup of the SecurityDomain until there
+    * is a SecurityDomain method invocation. This gets around the problem
+    * of a service not exposing its SecurityDomain binding until its started.
+    */ 
+   static class SecurityDomainProxy implements SecurityDomain
+   {
+      SecurityDomain delegate;
+      private String jndiName;
+
+      SecurityDomainProxy(String jndiName)
+      {
+         this.jndiName = jndiName;
+      }
+
+      private synchronized void initDelegate()
+      {
+         if( delegate == null )
+         {
+            try
+            {
+            InitialContext ctx = new InitialContext();
+            delegate = (SecurityDomain) ctx.lookup(jndiName);
+            }
+            catch(Exception e)
+            {
+               SecurityException se = new SecurityException("Failed to lookup SecurityDomain, "+jndiName);
+               se.initCause(e);
+               throw se;
+            }
+         }
+      }
+
+      public KeyStore getKeyStore() throws SecurityException
+      {
+         initDelegate();
+         return delegate.getKeyStore();
+      }
+
+      public KeyManagerFactory getKeyManagerFactory() throws SecurityException
+      {
+         initDelegate();
+         return delegate.getKeyManagerFactory();
+      }
+
+      public KeyStore getTrustStore() throws SecurityException
+      {
+         initDelegate();
+         return delegate.getTrustStore();
+      }
+
+      public TrustManagerFactory getTrustManagerFactory() throws SecurityException
+      {
+         initDelegate();
+         return delegate.getTrustManagerFactory();
+      }
+
+      public String getSecurityDomain()
+      {
+         initDelegate();
+         return delegate.getSecurityDomain();
+      }
+
+      public boolean isValid(Principal principal, Object credential)
+      {
+         return this.isValid(principal, credential, null);
+      }
+
+      public boolean isValid(Principal principal, Object credential,
+         Subject activeSubject)
+      {
+         initDelegate();
+         return delegate.isValid(principal, credential, activeSubject);
+      }
+
+      public Subject getActiveSubject()
+      {
+         initDelegate();
+         return delegate.getActiveSubject();
+      }
+
+      public Principal getPrincipal(Principal principal)
+      {
+         initDelegate();
+         return delegate.getPrincipal(principal);
+      }
+      
+      /**
+       * @see AuthenticationManager#getTargetPrincipal(Principal,Map)
+       */
+      public Principal getTargetPrincipal(Principal anotherDomainPrincipal, Map contextMap)
+      {
+         throw new RuntimeException("Not implemented yet");
+      }
+
+      public boolean doesUserHaveRole(Principal principal, Set roles)
+      {
+         initDelegate();
+         return delegate.doesUserHaveRole(principal, roles);
+      }
+
+      public Set getUserRoles(Principal principal)
+      {
+         initDelegate();
+         return delegate.getUserRoles(principal);
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/ssl/ClientSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/ClientSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/ClientSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,153 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Hashtable;
+import javax.net.SocketFactory;
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+import org.jboss.logging.Logger;
+
+/** An implementation of SocketFactory that uses the JSSE
+ default SSLSocketFactory to create a client SSLSocket.
+ *
+ * @author  Scott.Stark at jboss.org
+ * @version $Revision: 45653 $
+ */
+public class ClientSocketFactory extends SocketFactory
+   implements HandshakeCompletedListener, Serializable
+{
+   public static final String HANDSHAKE_COMPLETE_LISTENER =
+      "org.jboss.security.ssl.HandshakeCompletedListener";
+   static final long serialVersionUID = -2762336418317218104L;
+   private static Logger log = Logger.getLogger(ClientSocketFactory.class);
+   private boolean wantsClientAuth = true;
+   private boolean needsClientAuth = false;
+
+   /** Creates new ClientSocketFactory */
+   public ClientSocketFactory()
+   {
+   }
+
+   public boolean isWantsClientAuth()
+   {
+      return wantsClientAuth;
+   }
+   public void setWantsClientAuth(boolean wantsClientAuth)
+   {
+      this.wantsClientAuth = wantsClientAuth;
+   }
+
+   public boolean isNeedsClientAuth()
+   {
+      return needsClientAuth;
+   }
+   public void setNeedsClientAuth(boolean needsClientAuth)
+   {
+      this.needsClientAuth = needsClientAuth;
+   }
+
+   /** Create a client socket connected to the specified host and port.
+   * @param serverHost - the host name
+   * @param serverPort - the port number
+   * @return a socket connected to the specified host and port.
+   * @exception IOException if an I/O error occurs during socket creation.
+   */
+   public Socket createSocket(String serverHost, int serverPort)
+      throws IOException, UnknownHostException
+   {
+      InetAddress serverAddr = InetAddress.getByName(serverHost);
+      return this.createSocket(serverAddr, serverPort);
+   }
+
+   public Socket createSocket(String serverHost, int serverPort,
+      InetAddress clientAddr, int clientPort)
+      throws IOException, UnknownHostException
+   {
+      InetAddress serverAddr = InetAddress.getByName(serverHost);
+      return this.createSocket(serverAddr, serverPort, clientAddr, clientPort);
+   }
+   public Socket createSocket(InetAddress serverAddr, int serverPort)
+      throws IOException
+   {
+      return this.createSocket(serverAddr, serverPort, null, 0);
+   }
+   public Socket createSocket(InetAddress serverAddr, int serverPort,
+      InetAddress clientAddr, int clientPort)
+      throws IOException
+   {
+      SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+      SSLSocket socket = (SSLSocket) factory.createSocket(serverAddr, serverPort, clientAddr, clientPort);
+      socket.addHandshakeCompletedListener(this);
+      socket.setNeedClientAuth(needsClientAuth);
+      socket.setWantClientAuth(wantsClientAuth);
+      return socket;
+   }
+
+   public boolean equals(Object obj)
+   {
+      return obj instanceof ClientSocketFactory;
+   }
+   public int hashCode()
+   {
+      return getClass().getName().hashCode();
+   }
+
+   public void handshakeCompleted(HandshakeCompletedEvent event)
+   {
+      if( log.isTraceEnabled() )
+      {
+         String cipher = event.getCipherSuite();
+         SSLSession session = event.getSession();
+         String peerHost = session.getPeerHost();
+         log.debug("SSL handshakeCompleted, cipher="+cipher
+            +", peerHost="+peerHost);
+      }
+
+      /* See if there is a HANDSHAKE_COMPLETE_LISTENER. This is not done from
+      within a priviledged action as access to the SSL session through the
+      callback is not considered an implementation detail.
+      */
+      try
+      {
+         Hashtable env = System.getProperties();
+         HandshakeCompletedListener listener =
+            (HandshakeCompletedListener) env.get(HANDSHAKE_COMPLETE_LISTENER);
+         if( listener != null )
+            listener.handshakeCompleted(event);
+      }
+      catch(Throwable e)
+      {
+         log.debug("Failed to forward handshakeCompleted", e);
+      }
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/ssl/Context.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/Context.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/Context.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,92 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SecurityDomain;
+
+/** 
+ * Utility class with a static method that returns an initialized JSSE 
+ * SSLContext for a given JBossSX SecurityDomain.
+ *
+ * @see javax.net.ssl.KeyManagerFactory
+ * @see javax.net.ssl.SSLContext
+ * @see javax.net.ssl.TrustManager
+ * @see javax.net.ssl.TrustManagerFactory
+ * @see org.jboss.security.SecurityDomain
+ * 
+ * @author  Scott.Stark at jboss.org
+ * @author <a href="mailto:reverbel at ime.usp.br">Francisco Reverbel</a>
+ *
+ * @version $Revision: 37459 $
+ */
+class Context
+{
+   private static Logger log = Logger.getLogger(Context.class);
+
+   /*
+    * Returns an initialized JSSE SSLContext that uses the KeyManagerFactory
+    * and TrustManagerFactory objects encapsulated by a given JBossSX 
+    * SecurityDomain.
+    */
+   static SSLContext forDomain(SecurityDomain securityDomain)
+      throws IOException
+   {
+      SSLContext sslCtx = null;
+      try
+      {
+         sslCtx = SSLContext.getInstance("TLS");
+         KeyManagerFactory keyMgr = securityDomain.getKeyManagerFactory();
+         if( keyMgr == null )
+            throw new IOException("KeyManagerFactory is null for security domain: "+securityDomain.getSecurityDomain());
+         TrustManagerFactory trustMgr = securityDomain.getTrustManagerFactory();
+         TrustManager[] trustMgrs = null;
+         if( trustMgr != null )
+            trustMgrs = trustMgr.getTrustManagers();
+         sslCtx.init(keyMgr.getKeyManagers(), trustMgrs, null);
+         return sslCtx;
+      }
+      catch(NoSuchAlgorithmException e)
+      {
+         log.error("Failed to get SSLContext for TLS algorithm", e);
+         throw new IOException("Failed to get SSLContext for TLS algorithm");
+      }
+      catch(KeyManagementException e)
+      {
+         log.error("Failed to init SSLContext", e);
+         throw new IOException("Failed to init SSLContext");
+      }
+      catch(SecurityException e)
+      {
+         log.error("Failed to init SSLContext", e);
+         throw new IOException("Failed to init SSLContext");
+      }
+   }
+}

Added: trunk/security/src/main/org/jboss/security/ssl/DomainServerSocket.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/DomainServerSocket.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/DomainServerSocket.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,105 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.ssl;
+
+import java.net.Socket;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.SSLSession;
+
+import javassist.util.proxy.MethodHandler;
+
+/**
+ * A wrapper around SSLServerSocket that intercepts the accept call to add a
+ * HandshakeCompletedListener to the resulting SSLSocket so that we can build
+ * a session id to SSLSession map.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 44285 $
+ */
+class DomainServerSocket
+   implements MethodHandler, HandshakeCompletedListener
+{
+   private SSLServerSocket delegate;
+
+   DomainServerSocket(SSLServerSocket delegate)
+   {
+      this.delegate = delegate;
+   }
+
+   public Object invoke(Object self, Method method, Method method1, Object[] args)
+      throws Exception
+   {
+      Object rtn = null;
+      if( method.getName().equals("accept") )
+         rtn = this.accept();
+      else
+      {
+         try
+         {
+            rtn = method.invoke(delegate, args);
+         }
+         catch (InvocationTargetException e)
+         {
+            Throwable t = e.getTargetException();
+            if( t instanceof Exception )
+               throw (Exception) t;
+            else if( t instanceof Error )
+               throw (Error) t;
+            // Not good, but simply cannot throw a Throwable
+            throw e;
+         }
+      }
+      return rtn;
+   }
+
+   public Socket accept()
+      throws IOException
+   {
+      SSLSocket socket = (SSLSocket) delegate.accept();
+      socket.addHandshakeCompletedListener(this);
+      return socket;
+   }
+
+   public void handshakeCompleted(HandshakeCompletedEvent event)
+   {
+      SSLSession session = event.getSession();
+      String sessionID = null;
+      byte[] id = session.getId();
+      try
+      {
+         sessionID = new String(id, "UTF-8");
+      }
+      catch (UnsupportedEncodingException e)
+      {
+         sessionID = new String(id);
+      }
+      DomainServerSocketFactory.putSSLSession(sessionID, session);
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/ssl/DomainServerSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/DomainServerSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/DomainServerSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,306 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.WeakHashMap;
+import javax.naming.InitialContext;
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLSession;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SecurityDomain;
+import javassist.util.proxy.ProxyFactory;
+
+/** An implementation of ServerSocketFactory that creates SSL server sockets
+ using the JSSE SSLContext and a JBossSX SecurityDomain for the KeyManagerFactory
+ and TrustManagerFactory objects.
+
+ @see javax.net.ssl.SSLContext
+ @see org.jboss.security.SecurityDomain
+
+ at author  Scott.Stark at jboss.org
+ at version $Revision: 44910 $
+*/
+public class DomainServerSocketFactory extends SSLServerSocketFactory
+{
+   private static Logger log = Logger.getLogger(DomainServerSocketFactory.class);
+   /** WeakHashMap<String, SSLSession> */
+   private static WeakHashMap sessionMap = new WeakHashMap();
+
+   private transient SecurityDomain securityDomain;
+   private transient InetAddress bindAddress;
+   private transient SSLContext sslCtx = null;
+   private boolean wantsClientAuth = true;
+   private boolean needsClientAuth = false;
+   private String[] cipherSuites;
+   private String[] protocols;
+
+   /** The default ServerSocketFactory which looks to the java:/jaas/other
+    security domain configuration.
+    */
+   public static ServerSocketFactory getDefault()
+   {
+      DomainServerSocketFactory ssf = null;
+      try
+      {
+         InitialContext iniCtx = new InitialContext();
+         SecurityDomain sd = (SecurityDomain) iniCtx.lookup("java:/jaas/other");
+         ssf = new DomainServerSocketFactory(sd);
+      }
+      catch(Exception e)
+      {
+         log.error("Failed to create default ServerSocketFactory", e);
+      }
+      return ssf;
+   }
+
+   public static synchronized SSLSession getSSLSession(String sessionID)
+   {
+      SSLSession session = (SSLSession) sessionMap.get(sessionID);
+      return session;
+   }
+   static synchronized SSLSession putSSLSession(String sessionID, SSLSession session)
+   {
+      SSLSession prevSession = (SSLSession) sessionMap.put(sessionID, session);
+      return prevSession;
+   }
+   static synchronized SSLSession removeSSLSession(String sessionID)
+   {
+      SSLSession session = (SSLSession) sessionMap.remove(sessionID);
+      return session;
+   }
+
+   /** A default constructor for use when created by Class.newInstance. The
+    factory is not usable until its SecurityDomain has been established.
+    */
+   public DomainServerSocketFactory()
+   {
+   }
+   /** Create a socket factory instance that uses the given SecurityDomain
+    as the source for the SSL KeyManagerFactory and TrustManagerFactory.
+    */
+   public DomainServerSocketFactory(SecurityDomain securityDomain) throws IOException
+   {
+      if( securityDomain == null )
+         throw new IOException("The securityDomain may not be null");
+      this.securityDomain = securityDomain;
+   }
+
+   public String getBindAddress()
+   {
+      String address = null;
+      if( bindAddress != null )
+         address = bindAddress.getHostAddress();
+      return address;
+   }
+   public void setBindAddress(String host) throws UnknownHostException
+   {
+      bindAddress = InetAddress.getByName(host);
+   }
+
+   public SecurityDomain getSecurityDomain()
+   {
+      return securityDomain;
+   }
+   public void setSecurityDomain(SecurityDomain securityDomain)
+   {
+      this.securityDomain = securityDomain;
+   }
+
+   public boolean isWantsClientAuth()
+   {
+      return wantsClientAuth;
+   }
+   public void setWantsClientAuth(boolean wantsClientAuth)
+   {
+      this.wantsClientAuth = wantsClientAuth;
+   }
+
+   public boolean isNeedsClientAuth()
+   {
+      return needsClientAuth;
+   }
+   public void setNeedsClientAuth(boolean needsClientAuth)
+   {
+      this.needsClientAuth = needsClientAuth;
+   }
+
+   /**
+    @return current set of cipher suite names
+    */
+   public String[] getCipherSuites()
+   {
+      return cipherSuites;
+   }
+   /**
+    @param cipherSuites - set of cipher suite names to use
+    */
+   public void setCipherSuites(String[] cipherSuites)
+   {
+      this.cipherSuites = cipherSuites;
+   }
+
+   /**
+    This is an error due to a typo in the ciperSuites ivar
+    @deprecated use getCipherSuites 
+    @return current set of cipher suite names
+    */
+   public String[] getCiperSuites()
+   {
+      return cipherSuites;
+   }
+
+   /**
+    This is an error due to a typo in the ciperSuites ivar
+    @deprecated use getCipherSuites     
+    @param cipherSuites - set of cipher suite names to use
+    */
+   public void setCiperSuites(String[] cipherSuites)
+   {
+      this.cipherSuites = cipherSuites;
+   }
+
+   public String[] getProtocols()
+   {
+      return protocols;
+   }
+   public void setProtocols(String[] protocols)
+   {
+      this.protocols = protocols;
+   }
+
+// --- Begin SSLServerSocketFactory interface methods
+   public ServerSocket createServerSocket(int port) throws IOException
+   {
+      return createServerSocket(port, 50, bindAddress);
+   }
+   public ServerSocket createServerSocket(int port, int backlog)
+      throws IOException
+   {
+      return createServerSocket(port, backlog, bindAddress);
+   }
+   /**
+    * Returns a server socket which uses only the specified network
+    * interface on the local host, is bound to a the specified port,
+    * and uses the specified connection backlog.  The socket is configured
+    * with the socket options (such as accept timeout) given to this factory.
+    *
+    * @param port the port to listen to
+    * @param backlog how many connections are queued
+    * @param ifAddress the network interface address to use
+    *
+    * @exception IOException for networking errors
+    */
+   public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress)
+      throws IOException
+   {
+      initSSLContext();
+      SSLServerSocketFactory factory = sslCtx.getServerSocketFactory();
+      SSLServerSocket socket = (SSLServerSocket) factory.createServerSocket(port, backlog, ifAddress);
+      SSLSessionContext ctx = sslCtx.getServerSessionContext();
+      System.out.println(ctx);
+      if( log.isTraceEnabled() )
+      {
+         String[] supportedProtocols = socket.getSupportedProtocols();
+         log.debug("Supported protocols: " + Arrays.asList(supportedProtocols));
+         String[] supportedCipherSuites = socket.getSupportedCipherSuites();
+         log.debug("Supported CipherSuites: " + Arrays.asList(supportedCipherSuites));
+      }
+      socket.setNeedClientAuth(needsClientAuth);
+      socket.setWantClientAuth(wantsClientAuth);
+      if( protocols != null )
+         socket.setEnabledProtocols(protocols);
+      if( cipherSuites != null )
+         socket.setEnabledCipherSuites(cipherSuites);
+
+      DomainServerSocket handler = new DomainServerSocket(socket);
+      ProxyFactory pf = new ProxyFactory();
+      pf.setHandler(handler);
+      pf.setSuperclass(SSLServerSocket.class);
+      Class[] sig = {};
+      Object[] args = {};
+
+      SSLServerSocket proxy = null;
+      try
+      {
+         proxy = (SSLServerSocket) pf.create(sig, args);
+      }
+      catch (Exception e)
+      {
+         IOException ioe = new IOException("Failed to create SSLServerSocket proxy");
+         ioe.initCause(e);
+         throw ioe;
+      }
+      return proxy;
+   }
+
+   public String[] getDefaultCipherSuites()
+   {
+      String[] cipherSuites = {};
+      try
+      {
+         initSSLContext();
+         SSLServerSocketFactory factory = sslCtx.getServerSocketFactory();
+         cipherSuites = factory.getDefaultCipherSuites();
+      }
+      catch(IOException e)
+      {
+         log.error("Failed to get default SSLServerSocketFactory", e);
+      }
+      return cipherSuites;
+   }
+
+   public String[] getSupportedCipherSuites()
+   {
+      String[] cipherSuites = {};
+      try
+      {
+         initSSLContext();
+         SSLServerSocketFactory factory = sslCtx.getServerSocketFactory();
+         cipherSuites = factory.getSupportedCipherSuites();
+      }
+      catch(IOException e)
+      {
+         log.error("Failed to get default SSLServerSocketFactory", e);
+      }
+      return cipherSuites;
+   }
+
+// --- End SSLServerSocketFactory interface methods
+
+   private void initSSLContext()
+      throws IOException
+   {
+      if( sslCtx != null )
+         return;
+      sslCtx = Context.forDomain(securityDomain);
+   }
+}

Added: trunk/security/src/main/org/jboss/security/ssl/DomainSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/DomainSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/DomainSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,271 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Hashtable;
+import javax.naming.InitialContext;
+import javax.net.SocketFactory;
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SecurityDomain;
+
+/**
+ * An implementation of SocketFactory that creates SSL sockets using the 
+ * JSSE SSLContext and a JBossSX SecurityDomain for the KeyManagerFactory 
+ * and TrustManagerFactory objects.
+ *
+ * @see javax.net.ssl.SSLContext
+ * @see org.jboss.security.SecurityDomain
+ *
+ * @author  Scott.Stark at jboss.org
+ * @author <a href="mailto:reverbel at ime.usp.br">Francisco Reverbel</a>
+ *
+ * @version $Revision: 37459 $
+ */
+public class DomainSocketFactory 
+   extends SSLSocketFactory
+   implements HandshakeCompletedListener
+{
+   public static final String HANDSHAKE_COMPLETE_LISTENER =
+      "org.jboss.security.ssl.HandshakeCompletedListener";
+   private static Logger log = Logger.getLogger(DomainSocketFactory.class);
+   private transient SecurityDomain securityDomain;
+   private transient SSLContext sslCtx = null;
+   private boolean wantsClientAuth = true;
+   private boolean needsClientAuth = false;
+
+   /** 
+    * A default constructor for use when created by Class.newInstance. The
+    * factory is not usable until its SecurityDomain has been established.
+    */
+   public DomainSocketFactory()
+   {
+   }
+
+   /** 
+    * Create a socket factory instance that uses the given SecurityDomain
+    * as the source for the SSL KeyManagerFactory and TrustManagerFactory.
+    */
+   public DomainSocketFactory(SecurityDomain securityDomain) 
+      throws IOException
+   {
+      if( securityDomain == null )
+         throw new IOException("The securityDomain may not be null");
+      this.securityDomain = securityDomain;
+   }
+
+   public SecurityDomain getSecurityDomain()
+   {
+      return securityDomain;
+   }
+
+   public void setSecurityDomain(SecurityDomain securityDomain)
+   {
+      this.securityDomain = securityDomain;
+   }
+
+   public boolean isWantsClientAuth()
+   {
+      return wantsClientAuth;
+   }
+   public void setWantsClientAuth(boolean wantsClientAuth)
+   {
+      this.wantsClientAuth = wantsClientAuth;
+   }
+
+   public boolean isNeedsClientAuth()
+   {
+      return needsClientAuth;
+   }
+   public void setNeedsClientAuth(boolean needsClientAuth)
+   {
+      this.needsClientAuth = needsClientAuth;
+   }
+
+   // SSLSocketFactory methods --------------------------------------
+
+   /** 
+    * Create a client socket connected to the specified host and port.
+    * 
+    * @param serverHost - the host name
+    * @param serverPort - the port number
+    * @return a socket connected to the specified host and port.
+    * @exception IOException if an I/O error occurs during socket creation.
+    */
+   public Socket createSocket(String serverHost, int serverPort)
+      throws IOException, UnknownHostException
+   {
+      InetAddress serverAddr = InetAddress.getByName(serverHost);
+      return this.createSocket(serverAddr, serverPort);
+   }
+
+   public Socket createSocket(String serverHost, int serverPort,
+                              InetAddress clientAddr, int clientPort)
+      throws IOException, UnknownHostException
+   {
+      InetAddress serverAddr = InetAddress.getByName(serverHost);
+      return this.createSocket(serverAddr, serverPort, clientAddr, clientPort);
+   }
+
+   public Socket createSocket(InetAddress serverAddr, int serverPort)
+      throws IOException
+   {
+      return this.createSocket(serverAddr, serverPort, null, 0);
+   }
+
+   public Socket createSocket(InetAddress serverAddr, int serverPort,
+                              InetAddress clientAddr, int clientPort)
+      throws IOException
+   {
+      initSSLContext();
+      SSLSocketFactory factory = sslCtx.getSocketFactory();
+      SSLSocket socket = 
+         (SSLSocket)factory.createSocket(serverAddr, serverPort, 
+                                         clientAddr, clientPort);
+      String[] supportedProtocols = socket.getSupportedProtocols();
+      log.debug("Supported protocols: " + Arrays.asList(supportedProtocols));
+      String[] protocols = supportedProtocols; // {"SSLv3"};
+      socket.setEnabledProtocols(protocols);
+      socket.addHandshakeCompletedListener(this);
+      socket.setNeedClientAuth(needsClientAuth);
+      socket.setWantClientAuth(wantsClientAuth);
+      return socket;
+   }
+
+   public Socket createSocket(Socket s, String host, 
+                              int port, boolean autoClose) 
+      throws IOException
+   {
+      initSSLContext();
+      SSLSocketFactory factory = sslCtx.getSocketFactory();
+      SSLSocket socket = 
+         (SSLSocket)factory.createSocket(s, host, port, autoClose);
+      socket.addHandshakeCompletedListener(this);
+      return socket;
+   }
+
+   public String[] getDefaultCipherSuites()
+   {
+      String[] cipherSuites = {};
+      try
+      {
+         initSSLContext();
+         SSLSocketFactory factory = sslCtx.getSocketFactory();
+         cipherSuites = factory.getDefaultCipherSuites();
+      }
+      catch(IOException e)
+      {
+         log.error("Failed to get default SSLSocketFactory", e);
+      }      
+      return cipherSuites;
+   }
+   
+   public String[] getSupportedCipherSuites()
+   {
+      String[] cipherSuites = {};
+      try
+      {
+         initSSLContext();
+         SSLSocketFactory factory = sslCtx.getSocketFactory();
+         cipherSuites = factory.getSupportedCipherSuites();
+      }
+      catch(IOException e)
+      {
+         log.error("Failed to get default SSLSocketFactory", e);
+      }      
+      return cipherSuites;
+   }
+   
+   /** 
+    * The default SocketFactory which looks to the java:/jaas/other
+    * security domain configuration.
+    */
+   public static SocketFactory getDefault()
+   {
+      DomainSocketFactory ssf = null;
+      try
+      {
+         InitialContext iniCtx = new InitialContext();
+         SecurityDomain sd = (SecurityDomain)iniCtx.lookup("java:/jaas/other");
+         ssf = new DomainSocketFactory(sd);
+      }
+      catch(Exception e)
+      {
+         log.error("Failed to create default SocketFactory", e);
+      }
+      return ssf;
+   }
+   
+   // HandshakeCompletedListener method -----------------------------
+
+   public void handshakeCompleted(HandshakeCompletedEvent event)
+   {
+      Logger log = Logger.getLogger(ClientSocketFactory.class);
+      if( log.isTraceEnabled() )
+      {
+         String cipher = event.getCipherSuite();
+         SSLSession session = event.getSession();
+         String peerHost = session.getPeerHost();
+         log.debug("SSL handshakeCompleted, cipher="+cipher
+            +", peerHost="+peerHost);
+      }
+
+      /* See if there is a HANDSHAKE_COMPLETE_LISTENER. This is not done from
+      within a priviledged action as access to the SSL session through the
+      callback is not considered an implementation detail.
+      */
+      try
+      {
+         Hashtable env = System.getProperties();
+         HandshakeCompletedListener listener =
+            (HandshakeCompletedListener) env.get(HANDSHAKE_COMPLETE_LISTENER);
+         if( listener != null )
+            listener.handshakeCompleted(event);
+      }
+      catch(Throwable e)
+      {
+         log.debug("Failed to foward handshakeCompleted", e);
+      }
+   }
+
+   // Private method ------------------------------------------------
+
+   private void initSSLContext()
+      throws IOException
+   {
+      if( sslCtx != null )
+         return;
+      sslCtx = Context.forDomain(securityDomain);
+   }
+
+}

Added: trunk/security/src/main/org/jboss/security/ssl/RMISSLClientSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/RMISSLClientSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/RMISSLClientSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,147 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.rmi.server.RMIClientSocketFactory;
+import java.security.cert.Certificate;
+import java.util.Hashtable;
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+import org.jboss.logging.Logger;
+
+/** An implementation of RMIClientSocketFactory that uses the JSSE
+ default SSLSocketFactory to create a client SSLSocket.
+ *
+ * @author  Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public class RMISSLClientSocketFactory implements HandshakeCompletedListener,
+   RMIClientSocketFactory, Serializable
+{
+   public static final String HANDSHAKE_COMPLETE_LISTENER =
+      "org.jboss.security.ssl.HandshakeCompletedListener";
+   private static Logger log = Logger.getLogger(RMISSLClientSocketFactory.class);
+   private static final long serialVersionUID = -6412485012870705607L;
+   private boolean wantsClientAuth = true;
+   private boolean needsClientAuth = false;
+
+   /** Creates new RMISSLClientSocketFactory */
+   public RMISSLClientSocketFactory()
+   {
+   }
+
+   public boolean isWantsClientAuth()
+   {
+      return wantsClientAuth;
+   }
+   public void setWantsClientAuth(boolean wantsClientAuth)
+   {
+      this.wantsClientAuth = wantsClientAuth;
+   }
+
+   public boolean isNeedsClientAuth()
+   {
+      return needsClientAuth;
+   }
+   public void setNeedsClientAuth(boolean needsClientAuth)
+   {
+      this.needsClientAuth = needsClientAuth;
+   }
+
+   /** Create a client socket connected to the specified host and port.
+   * @param host - the host name
+   * @param port - the port number
+   * @return a socket connected to the specified host and port.
+   * @exception IOException if an I/O error occurs during socket creation.
+   */
+   public java.net.Socket createSocket(String host, int port)
+      throws IOException
+   {
+      SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+      SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
+      socket.addHandshakeCompletedListener(this);
+      socket.setWantClientAuth(wantsClientAuth);
+      socket.setNeedClientAuth(needsClientAuth);
+      log.debug("createSocket, host="+host+", port="+port
+         +",needsClientAuth="+needsClientAuth+", wantsClientAuth="+wantsClientAuth);
+      return socket;
+   }
+
+   public boolean equals(Object obj)
+   {
+      return obj instanceof RMISSLClientSocketFactory;
+   }
+   public int hashCode()
+   {
+      return getClass().getName().hashCode();
+   }
+
+   public void handshakeCompleted(HandshakeCompletedEvent event)
+   {
+      String cipher = event.getCipherSuite();
+      SSLSession session = event.getSession();
+      String peerHost = session.getPeerHost();
+      Certificate[] localCerts = event.getLocalCertificates();
+      Certificate[] peerCerts = null;
+      try
+      {
+         peerCerts = event.getPeerCertificates();
+      }
+      catch(Exception e)
+      {
+         log.debug("Failed to retrieve peer certs", e);
+      }
+      log.debug("SSL handshakeCompleted, cipher="+cipher
+         +", peerHost="+peerHost);
+      int count = localCerts != null ? localCerts.length : 0;
+      log.debug("ClientCertChain length: "+count);
+      for(int n = 0; n < count; n ++)
+         log.debug("Cert["+n+"]="+localCerts[n]);
+      count = peerCerts != null ? peerCerts.length : 0;
+      log.debug("PeerCertChain length: "+count);
+      for(int n = 0; n < count; n ++)
+         log.debug("Cert["+n+"]="+peerCerts[n]);
+   
+      /* See if there is a HANDSHAKE_COMPLETE_LISTENER. This is not done from
+      within a priviledged action as access to the SSL session through the
+      callback is not considered an implementation detail.
+      */
+      try
+      {
+         Hashtable env = System.getProperties();
+         HandshakeCompletedListener listener =
+            (HandshakeCompletedListener) env.get(HANDSHAKE_COMPLETE_LISTENER);
+         if( listener != null )
+            listener.handshakeCompleted(event);
+      }
+      catch(Throwable e)
+      {
+         log.debug("Failed to foward handshakeCompleted", e);
+      }
+   }
+}
\ No newline at end of file

Added: trunk/security/src/main/org/jboss/security/ssl/RMISSLServerSocketFactory.java
===================================================================
--- trunk/security/src/main/org/jboss/security/ssl/RMISSLServerSocketFactory.java	                        (rev 0)
+++ trunk/security/src/main/org/jboss/security/ssl/RMISSLServerSocketFactory.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,131 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.security.ssl;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.rmi.server.RMIServerSocketFactory;
+
+import org.jboss.security.SecurityDomain;
+
+/** An implementation of RMIServerSocketFactory that uses a
+ DomainServerSocketFactory for its implementation. This class is just an
+ adaptor from the RMIServerSocketFactory to the DomainServerSocketFactory.
+
+ This class is not suitable for RMI object that require a Serializable socket
+ factory like activatable services. The reason for this limitation is that
+ a SecurityDomain is not serializable due to its association with a local
+ KeyStore.
+
+ at author Scott.Stark at jboss.org
+ at version $Revision: 37459 $
+*/
+public class RMISSLServerSocketFactory implements RMIServerSocketFactory
+{
+   private DomainServerSocketFactory domainFactory;
+
+   /** Creates new RMISSLServerSocketFactory initialized with a
+    DomainServerSocketFactory with not security domain. The setSecurityDomain
+    method must be invoked to establish the correct non-default value.
+    */
+   public RMISSLServerSocketFactory()
+   {
+      domainFactory = new DomainServerSocketFactory();
+   }
+
+   public String getBindAddress()
+   {
+      return domainFactory.getBindAddress();
+   }
+   public void setBindAddress(String host) throws UnknownHostException
+   {
+      domainFactory.setBindAddress(host);
+   }
+
+   public SecurityDomain getSecurityDomain()
+   {
+      return domainFactory.getSecurityDomain();
+   }
+   public void setSecurityDomain(SecurityDomain securityDomain)
+   {
+      domainFactory.setSecurityDomain(securityDomain);
+   }
+
+   public boolean isWantsClientAuth()
+   {
+      return domainFactory.isWantsClientAuth();
+   }
+   public void setWantsClientAuth(boolean wantsClientAuth)
+   {
+      domainFactory.setWantsClientAuth(wantsClientAuth);
+   }
+
+   public boolean isNeedsClientAuth()
+   {
+      return domainFactory.isNeedsClientAuth();
+   }
+   public void setNeedsClientAuth(boolean needsClientAuth)
+   {
+      domainFactory.setNeedsClientAuth(needsClientAuth);
+   }
+   public String[] getCiperSuites()
+   {
+      return domainFactory.getCiperSuites();
+   }
+   public void setCiperSuites(String[] ciperSuites)
+   {
+      domainFactory.setCiperSuites(ciperSuites);
+   }
+
+   public String[] getProtocols()
+   {
+      return domainFactory.getProtocols();
+   }
+   public void setProtocols(String[] protocols)
+   {
+      domainFactory.setProtocols(protocols);
+   }
+
+   /**
+    * Create a server socket on the specified port (port 0 indicates
+    * an anonymous port).
+    * @param  port the port number
+    * @return the server socket on the specified port
+    * @exception IOException if an I/O error occurs during server socket
+    * creation
+    */
+   public ServerSocket createServerSocket(int port)
+      throws IOException
+   {
+      return domainFactory.createServerSocket(port);
+   }
+
+   public boolean equals(Object obj)
+   {
+      return obj instanceof RMISSLServerSocketFactory;
+   }
+   public int hashCode()
+   {
+      return getClass().getName().hashCode();
+   }
+}

Added: trunk/security/src/tests/org/jboss/test/LoginContextTestCase.java
===================================================================
--- trunk/security/src/tests/org/jboss/test/LoginContextTestCase.java	                        (rev 0)
+++ trunk/security/src/tests/org/jboss/test/LoginContextTestCase.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,318 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test;
+
+import java.util.Iterator;
+import java.util.Set;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.Subject;
+
+import junit.framework.TestCase;
+
+import org.jboss.security.auth.login.XMLLoginConfigImpl;
+import org.jboss.security.SimplePrincipal;
+
+public class LoginContextTestCase extends TestCase
+{
+
+   public LoginContextTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected void setUp() throws Exception
+   {
+      System.setOut(System.err);
+      XMLLoginConfigImpl config = new XMLLoginConfigImpl();
+      config.setConfigResource("login-config.xml");
+      config.loadConfig();
+      Configuration.setConfiguration(config);
+   }
+
+   private void validateSuccessfulLogin(LoginContext lc) throws LoginException
+   {
+      Subject subject = lc.getSubject();
+      assertTrue("case5 subject != null", subject != null);
+      boolean hasGuest = subject.getPrincipals().contains(new SimplePrincipal("guest"));
+      assertTrue("subject has guest principal", hasGuest);
+      lc.logout();
+      hasGuest = subject.getPrincipals().contains(new SimplePrincipal("guest"));
+      assertTrue("subject has guest principal", hasGuest == false);
+      Set publicCreds = subject.getPublicCredentials();
+      assertTrue("public creds has 'A public credential'",
+         publicCreds.contains("A public credential"));
+      Set privateCreds = subject.getPrivateCredentials();
+      assertTrue("private creds has 'A private credential'",
+         privateCreds.contains("A private credential"));
+      Iterator iter = privateCreds.iterator();
+      int count = 0;
+      while( iter.hasNext() )
+      {
+         iter.next();
+         count ++;
+      }
+      assertTrue("private creds has 1 entry", count == 1);
+   }
+
+   public void testCase1() throws Exception
+   {
+      LoginContext lc = new LoginContext("case1");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase2() throws Exception
+   {
+      LoginContext lc = new LoginContext("case2");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase3() throws Exception
+   {
+      LoginContext lc = new LoginContext("case3");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login3 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   /** This should fail because no login module succeeds
+    *
+    * @throws Exception
+    */
+   public void testCase4() throws Exception
+   {
+      LoginContext lc = new LoginContext("case4");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login4 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase5() throws Exception
+   {
+      LoginContext lc = new LoginContext("case5");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+   public void testCase6() throws Exception
+   {
+      LoginContext lc = new LoginContext("case6");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+   public void testCase7() throws Exception
+   {
+      LoginContext lc = new LoginContext("case7");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase8() throws Exception
+   {
+      LoginContext lc = new LoginContext("case8");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login8 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase9() throws Exception
+   {
+      LoginContext lc = new LoginContext("case9");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase10() throws Exception
+   {
+      LoginContext lc = new LoginContext("case10");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login10 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase11() throws Exception
+   {
+      LoginContext lc = new LoginContext("case11");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+   public void testCase12() throws Exception
+   {
+      LoginContext lc = new LoginContext("case12");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase13() throws Exception
+   {
+      LoginContext lc = new LoginContext("case13");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login13 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase14() throws Exception
+   {
+      LoginContext lc = new LoginContext("case14");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login14 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase15() throws Exception
+   {
+      LoginContext lc = new LoginContext("case15");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login15 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase16() throws Exception
+   {
+      LoginContext lc = new LoginContext("case16");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase17() throws Exception
+   {
+      LoginContext lc = new LoginContext("case17");
+      lc.login();
+      validateSuccessfulLogin(lc);
+   }
+
+   public void testCase18() throws Exception
+   {
+      LoginContext lc = new LoginContext("case18");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login18 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase19() throws Exception
+   {
+      LoginContext lc = new LoginContext("case19");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login19 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase20() throws Exception
+   {
+      LoginContext lc = new LoginContext("case20");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login20 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+   public void testCase21() throws Exception
+   {
+      LoginContext lc = new LoginContext("case21");
+      try
+      {
+         lc.login();
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+      Subject subject = lc.getSubject();
+      assertTrue("case21 subject == null", subject == null);
+   }
+
+   public void testCase22() throws Exception
+   {
+      LoginContext lc = new LoginContext("case22");
+      try
+      {
+         lc.login();
+         fail("LoginContext.login22 did not thrown an exception");
+      }
+      catch(LoginException e)
+      {
+         e.printStackTrace();
+      }
+   }
+
+}

Added: trunk/security/src/tests/org/jboss/test/SunConfigParserTestCase.java
===================================================================
--- trunk/security/src/tests/org/jboss/test/SunConfigParserTestCase.java	                        (rev 0)
+++ trunk/security/src/tests/org/jboss/test/SunConfigParserTestCase.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,129 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test;
+
+import java.io.InputStreamReader;
+import java.net.URL;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+import junit.framework.TestCase;
+
+import org.jboss.security.auth.login.SunConfigParser;
+import org.jboss.security.auth.login.XMLLoginConfigImpl;
+
+/** Tests of the Sun login configuration file format parser
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 37459 $
+ */
+public class SunConfigParserTestCase extends TestCase
+{
+
+   public SunConfigParserTestCase(String name)
+   {
+      super(name);
+   }
+
+   /** Test the Sun config file parser directly.
+    *
+    * @throws Exception
+    */
+   public void testParser() throws Exception
+   {
+      XMLLoginConfigImpl config = new XMLLoginConfigImpl();
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      URL configURL = loader.getResource("login-config.conf");
+      InputStreamReader configFile = new InputStreamReader(configURL.openStream());
+      SunConfigParser.doParse(configFile, config, true);
+
+      AppConfigurationEntry[] entry = config.getAppConfigurationEntry("case1");
+      assertTrue("case1 entry != null", entry != null);
+      assertTrue("case1.length == 2", entry.length == 2);
+      assertTrue("case1[0].module == org.jboss.test.TestLoginModule",
+         entry[0].getLoginModuleName().equals("org.jboss.test.TestLoginModule"));
+      assertTrue("case1[0].flag == required",
+         entry[0].getControlFlag() == LoginModuleControlFlag.REQUIRED);
+      assertTrue("case1[0].option(name) == 1.1",
+         entry[0].getOptions().get("name").equals("1.1"));
+      assertTrue("case1[0].option(succeed) == true",
+         entry[0].getOptions().get("succeed").equals("true"));
+      assertTrue("case1[0].option(throwEx) == false",
+         entry[0].getOptions().get("throwEx").equals("false"));
+
+      entry = config.getAppConfigurationEntry("case2");
+      assertTrue("case2 entry != null", entry != null);
+      assertTrue("case2.length == 2", entry.length == 2);
+      assertTrue("case2[0].module = org.jboss.test.TestLoginModule",
+         entry[0].getLoginModuleName().equals("org.jboss.test.TestLoginModule")); 
+      assertTrue("case2[0].flag == optional",
+         entry[0].getControlFlag() == LoginModuleControlFlag.OPTIONAL);
+      assertTrue("case2[1].option(name) == 2.2",
+         entry[1].getOptions().get("name").equals("2.2"));
+      assertTrue("case2[1].option(succeed) == false",
+         entry[1].getOptions().get("succeed").equals("false"));
+      assertTrue("case2[1].option(throwEx) == true",
+         entry[1].getOptions().get("throwEx").equals("true"));
+   }
+
+   /** Test the Sun config file parser by creating a XMLLoginConfig with a
+    * URL pointing to a Sun format config file.
+    *
+    * @throws Exception
+    */
+   public void testSunLoginConfig() throws Exception
+   {
+      XMLLoginConfigImpl config = new XMLLoginConfigImpl();
+      ClassLoader loader = Thread.currentThread().getContextClassLoader();
+      URL configURL = loader.getResource("login-config.conf");
+      config.setConfigURL(configURL);
+      config.loadConfig();
+
+      AppConfigurationEntry[] entry = config.getAppConfigurationEntry("case1");
+      assertTrue("case1 entry != null", entry != null);
+      assertTrue("case1.length == 2", entry.length == 2);
+      assertTrue("case1[0].module == org.jboss.test.TestLoginModule",
+         entry[0].getLoginModuleName().equals("org.jboss.test.TestLoginModule"));
+      assertTrue("case1[0].flag == required",
+         entry[0].getControlFlag() == LoginModuleControlFlag.REQUIRED);
+      assertTrue("case1[0].option(name) == 1.1",
+         entry[0].getOptions().get("name").equals("1.1"));
+      assertTrue("case1[0].option(succeed) == true",
+         entry[0].getOptions().get("succeed").equals("true"));
+      assertTrue("case1[0].option(throwEx) == false",
+         entry[0].getOptions().get("throwEx").equals("false"));
+
+      entry = config.getAppConfigurationEntry("case2");
+      assertTrue("case2 entry != null", entry != null);
+      assertTrue("case2.length == 2", entry.length == 2);
+      assertTrue("case2[0].module = org.jboss.test.TestLoginModule",
+         entry[0].getLoginModuleName().equals("org.jboss.test.TestLoginModule"));
+      assertTrue("case2[0].flag == optional",
+         entry[0].getControlFlag() == LoginModuleControlFlag.OPTIONAL);
+      assertTrue("case2[1].option(name) == 2.2",
+         entry[1].getOptions().get("name").equals("2.2"));
+      assertTrue("case2[1].option(succeed) == false",
+         entry[1].getOptions().get("succeed").equals("false"));
+      assertTrue("case2[1].option(throwEx) == true",
+         entry[1].getOptions().get("throwEx").equals("true"));
+   }
+}

Added: trunk/security/src/tests/org/jboss/test/ldap/LoginModulesTestCase.java
===================================================================
--- trunk/security/src/tests/org/jboss/test/ldap/LoginModulesTestCase.java	                        (rev 0)
+++ trunk/security/src/tests/org/jboss/test/ldap/LoginModulesTestCase.java	2007-05-16 03:26:51 UTC (rev 63068)
@@ -0,0 +1,815 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.ldap;
+
+import java.lang.reflect.Method;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.logging.Level; 
+import java.util.logging.ConsoleHandler;
+import javax.security.auth.Subject;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.jboss.logging.Logger;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.callback.UsernamePasswordHandler;
+import org.jboss.security.plugins.JaasSecurityDomain;
+
+/** Tests of the LoginModule classes.
+
+ @author Scott.Stark at jboss.org
+ @version $Revision: 58707 $
+ */
+public class LoginModulesTestCase extends TestCase
+{
+   static
+   {
+      try
+      {
+         Configuration.setConfiguration(new TestConfig());
+         System.out.println("Installed TestConfig as JAAS Configuration");
+         Logger.setPluginClassName("org.jboss.logging.JDK14LoggerPlugin");
+         java.util.logging.Logger security = java.util.logging.Logger.getLogger("org.jboss.security");
+         security.setLevel(Level.FINEST);
+         ConsoleHandler console = new ConsoleHandler();
+         console.setLevel(Level.FINEST);
+         security.addHandler(console);
+         Logger log = Logger.getLogger("org.jboss.security");
+         log.trace("Configured JDK trace logging");
+      }
+      catch(Exception e)
+      {
+         e.printStackTrace();
+      }
+   }
+   /** Hard coded login configurations for the test cases. The configuration
+    name corresponds to the unit test function that uses the configuration.
+    */
+   static class TestConfig extends Configuration
+   {
+      public void refresh()
+      {
+      }
+
+      public AppConfigurationEntry[] getAppConfigurationEntry(String name)
+      {
+         AppConfigurationEntry[] entry = null;
+         try
+         {
+            Class[] parameterTypes = {};
+            Method m = getClass().getDeclaredMethod(name, parameterTypes);
+            Object[] args = {};
+            entry = (AppConfigurationEntry[]) m.invoke(this, args);
+         }
+         catch(Exception e)
+         {
+         }
+         return entry;
+      }
+      AppConfigurationEntry[] testLdapExample1()
+      {
+         String name = "org.jboss.security.auth.spi.LdapLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+         options.put("principalDNPrefix", "uid=");
+         options.put("principalDNSuffix", ",ou=People,dc=jboss,dc=org");
+         options.put("rolesCtxDN", "ou=Roles,dc=jboss,dc=org");
+         options.put("uidAttributeID", "member");
+         options.put("matchOnUserDN", "true");
+         options.put("roleAttributeID", "cn");
+         options.put("roleAttributeIsDN", "false");
+         options.put("searchTimeLimit", "5000");
+         options.put("searchScope", "ONELEVEL_SCOPE");
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      AppConfigurationEntry[] testLdapExample11()
+      {
+         String name = "org.jboss.security.auth.spi.LdapLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+         options.put("java.naming.security.principal", "cn=Root,dc=jboss,dc=org");
+         options.put("java.naming.security.credentials", "secret1");
+
+         options.put("principalDNPrefix", "uid=");
+         options.put("principalDNSuffix", ",ou=People,dc=jboss,dc=org");
+         options.put("rolesCtxDN", "ou=Roles,dc=jboss,dc=org");
+         options.put("uidAttributeID", "member");
+         options.put("matchOnUserDN", "true");
+         options.put("roleAttributeID", "cn");
+         options.put("roleAttributeIsDN", "false");
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      AppConfigurationEntry[] testLdapExample11Encrypt()
+      {
+         String name = "org.jboss.security.auth.spi.LdapLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+         options.put("java.naming.security.principal", "cn=Root,dc=jboss,dc=org");
+         // secret1 encrypted
+         options.put("java.naming.security.credentials", "7hInTB4HCBL");
+
+         options.put("jaasSecurityDomain", "jboss.test:service=JaasSecurityDomain,domain=testLdapExample11Encrypt");
+         options.put("principalDNPrefix", "uid=");
+         options.put("principalDNSuffix", ",ou=People,dc=jboss,dc=org");
+         options.put("rolesCtxDN", "ou=Roles,dc=jboss,dc=org");
+         options.put("uidAttributeID", "member");
+         options.put("matchOnUserDN", "true");
+         options.put("roleAttributeID", "cn");
+         options.put("roleAttributeIsDN", "false");
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      AppConfigurationEntry[] testLdapExample2()
+      {
+         String name = "org.jboss.security.auth.spi.LdapLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+         options.put("principalDNPrefix", "uid=");
+         options.put("principalDNSuffix", ",ou=People,o=example2,dc=jboss,dc=org");
+         options.put("rolesCtxDN", "ou=Roles,o=example2,dc=jboss,dc=org");
+         options.put("uidAttributeID", "uid");
+         options.put("matchOnUserDN", "false");
+         options.put("roleAttributeID", "memberOf");
+         options.put("roleAttributeIsDN", "true");
+         options.put("roleNameAttributeID", "cn");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+
+      /**
+      testLdapExample21 {
+         org.jboss.security.auth.spi.LdapExtLoginModule
+            java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+            java.naming.provider.url="ldap://lamia/"
+            java.naming.security.authentication=simple
+            bindDN="cn=Root,dc=jboss,dc=org"
+            bindCredential=secret1
+            baseCtxDN="ou=People,dc=jboss,dc=org"
+            baseFilter="(uid={0})"
+            rolesCtxDN="ou=Roles,dc=jboss,dc=org";
+            roleFilter="(member={1})"
+            roleAttributeID="cn"
+            roleRecursion=0
+      };
+      */
+      AppConfigurationEntry[] testLdapExample21()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+         options.put("bindDN", "cn=Root,dc=jboss,dc=org");
+         options.put("bindCredential", "secret1");
+         options.put("baseCtxDN", "ou=People,dc=jboss,dc=org");
+         options.put("baseFilter", "(uid={0})");
+
+         options.put("rolesCtxDN", "ou=Roles,dc=jboss,dc=org");
+         options.put("roleFilter", "(member={1})");
+         options.put("roleAttributeID", "cn");
+         options.put("roleRecursion", "0");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      AppConfigurationEntry[] testLdapExample21Encrypt()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+         options.put("jaasSecurityDomain", "jboss.test:service=JaasSecurityDomain,domain=testLdapExample21Encrypt");
+         options.put("bindDN", "cn=Root,dc=jboss,dc=org");
+         // secret1 encrypted
+         options.put("bindCredential", "7hInTB4HCBL");
+         options.put("baseCtxDN", "ou=People,dc=jboss,dc=org");
+         options.put("baseFilter", "(uid={0})");
+
+         options.put("rolesCtxDN", "ou=Roles,dc=jboss,dc=org");
+         options.put("roleFilter", "(member={1})");
+         options.put("roleAttributeID", "cn");
+         options.put("roleRecursion", "0");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      /**
+      testLdapExample23 {
+         org.jboss.security.auth.spi.LdapExtLoginModule
+            java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+            java.naming.provider.url="ldap://lamia/"
+            java.naming.security.authentication=simple
+            bindDN="cn=Root,dc=jboss,dc=org"
+            bindCredential=secret1
+            baseCtxDN="ou=People,o=example3,dc=jboss,dc=org"
+            baseFilter="(cn={0})"
+            rolesCtxDN="ou=Roles,o=example3,dc=jboss,dc=org";
+            roleFilter="(member={1})"
+            roleAttributeID="cn"
+            roleRecursion=0
+      };
+      */
+      AppConfigurationEntry[] testLdapExample23()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+
+         options.put("bindDN", "cn=Root,dc=jboss,dc=org");
+         options.put("bindCredential", "secret1");
+         options.put("baseCtxDN", "ou=People,o=example3,dc=jboss,dc=org");
+         options.put("baseFilter", "(cn={0})");
+
+         options.put("rolesCtxDN", "ou=Roles,o=example3,dc=jboss,dc=org");
+         options.put("roleFilter", "(member={1})");
+         options.put("roleAttributeID", "cn");
+         options.put("roleRecursion", "0");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      /**
+      testLdapExample22 {
+         org.jboss.security.auth.spi.LdapExtLoginModule
+            java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+            java.naming.provider.url="ldap://lamia/"
+            java.naming.security.authentication=simple
+            bindDN="cn=Root,dc=jboss,dc=org"
+            bindCredential=secret1
+            baseCtxDN="ou=People,o=example2,dc=jboss,dc=org"
+            baseFilter="(uid={0})"
+            rolesCtxDN="ou=Roles,o=example2,dc=jboss,dc=org";
+            roleFilter="(uid={0})"
+            roleAttributeID="memberOf"
+            roleAttributeIsDN="true"
+            roleNameAttributeID="cn"
+            roleRecursion=0
+      };
+      */
+      AppConfigurationEntry[] testLdapExample22()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+
+         options.put("bindDN", "cn=Root,dc=jboss,dc=org");
+         options.put("bindCredential", "secret1");
+         options.put("baseCtxDN", "ou=People,o=example2,dc=jboss,dc=org");
+         options.put("baseFilter", "(uid={0})");
+
+         options.put("rolesCtxDN", "ou=Roles,o=example2,dc=jboss,dc=org");
+         options.put("roleFilter", "(uid={0})");
+         options.put("roleAttributeID", "memberOf");
+         options.put("roleAttributeIsDN", "true");
+         options.put("roleNameAttributeID", "cn");
+         options.put("roleRecursion", "0");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+      /**
+      testLdapExample24 {
+         org.jboss.security.auth.spi.LdapExtLoginModule
+            java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+            java.naming.provider.url="ldap://lamia/"
+            java.naming.security.authentication=simple
+            bindDN="cn=Root,dc=jboss,dc=org"
+            bindCredential=secret1
+            baseCtxDN="ou=People,o=example4,dc=jboss,dc=org"
+            baseFilter="(cn={0})"
+            rolesCtxDN="ou=Roles,o=example4,dc=jboss,dc=org";
+            roleFilter="(member={1})"
+            roleAttributeID="memberOf"
+            roleRecursion=1
+      };
+      */
+      AppConfigurationEntry[] testLdapExample24()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+         options.put("bindDN", "cn=Root,dc=jboss,dc=org");
+         options.put("bindCredential", "secret1");
+         options.put("baseCtxDN", "ou=People,o=example4,dc=jboss,dc=org");
+         options.put("baseFilter", "(cn={0})");
+
+         options.put("rolesCtxDN", "ou=Roles,o=example4,dc=jboss,dc=org");
+         options.put("roleFilter", "(member={1})");
+         options.put("roleAttributeID", "cn");
+         options.put("roleRecursion", "1");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+
+      AppConfigurationEntry[] testJBAS3312()
+      {
+         String name = "org.jboss.security.auth.spi.LdapExtLoginModule";
+         HashMap options = new HashMap();
+         options.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");
+         options.put("java.naming.provider.url", "ldap://lamia/");
+         options.put("java.naming.security.authentication", "simple");
+
+         options.put("bindDN", "cn=Root,DC=uz,DC=kuleuven,DC=ac,DC=be");
+         options.put("bindCredential", "root");
+         options.put("baseCtxDN", "ou=People,dc=uz,dc=kuleuven,dc=ac,dc=be");
+         options.put("baseFilter", "(sAMAccountName={0})");
+
+         options.put("rolesCtxDN", "OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be");
+         options.put("roleFilter", "(member={1})");
+         options.put("roleAttributeID", "memberOf");
+         options.put("roleAttributeIsDN", "true");
+         options.put("roleNameAttributeID", "cn");
+         options.put("roleRecursion", "5");
+         options.put("searchScope", "ONELEVEL_SCOPE");
+
+         AppConfigurationEntry ace = new AppConfigurationEntry(name,
+         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
+         AppConfigurationEntry[] entry = {ace};
+         return entry;
+      }
+
+   }
+
+   public LoginModulesTestCase(String testName)
+   {
+      super(testName);
+   }
+
+   public void testLdapExample1() throws Exception
+   {
+      System.out.println("testLdapExample1");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke", "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample1", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      assertTrue("Principals contains jduke", subject.getPrincipals().contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+   }
+   public void testLdapExample11() throws Exception
+   {
+      System.out.println("testLdapExample11");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke", "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample11", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      assertTrue("Principals contains jduke", subject.getPrincipals().contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+   }
+   public void testLdapExample11Encrypt() throws Exception
+   {
+      System.out.println("testLdapExample11Encrypt");
+      MBeanServer server = MBeanServerFactory.createMBeanServer("jboss");
+      JaasSecurityDomain secDomain = new JaasSecurityDomain("testLdapExample11Encrypt");
+      secDomain.setSalt("abcdefgh");
+      secDomain.setIterationCount(13);
+      secDomain.setKeyStorePass("master");
+      secDomain.setManagerServiceName(null);
+      secDomain.start();
+      ObjectName name = new ObjectName("jboss.test:service=JaasSecurityDomain,domain=testLdapExample11Encrypt");
+      server.registerMBean(secDomain, name);
+
+      // secret1 encrypts to 7hInTB4HCBL
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke", "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample11Encrypt", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      assertTrue("Principals contains jduke", subject.getPrincipals().contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+      MBeanServerFactory.releaseMBeanServer(server);
+   }
+   /*
+version: 1
+dn: o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: dcObject
+objectClass: organization
+dc: jboss
+o: JBoss
+
+dn: ou=People,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: People
+
+dn: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: uidObject
+objectClass: person
+objectClass: inetOrgPerson
+cn: Java Duke
+employeeNumber: judke-123
+sn: Duke
+uid: jduke
+userPassword:: dGhlZHVrZQ==
+
+dn: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: uidObject
+objectClass: person
+objectClass: inetOrgPerson
+cn: Java Duke2
+employeeNumber: judke2-123
+sn: Duke2
+uid: jduke2
+userPassword:: dGhlZHVrZTI=
+
+dn: ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: organizationalUnit
+ou: Roles
+
+dn: uid=jduke,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: groupUserEx
+memberOf: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
+memberOf: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
+uid: jduke
+
+dn: uid=jduke2,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: groupUserEx
+memberOf: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
+memberOf: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
+uid: jduke2
+
+dn: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: groupOfNames
+cn: Echo
+description: the echo role
+member: uid=jduke,ou=People,dc=jboss,dc=org
+
+dn: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: groupOfNames
+objectClass: top
+cn: TheDuke
+description: the duke role
+member: uid=jduke,ou=People,o=example2,dc=jboss,dc=org
+
+dn: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: groupOfNames
+cn: Echo2
+description: the Echo2 role
+member: uid=jduke2,ou=People,dc=jboss,dc=org
+
+dn: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: groupOfNames
+objectClass: top
+cn: TheDuke2
+description: the duke2 role
+member: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org
+
+dn: cn=JBossAdmin,ou=Roles,o=example2,dc=jboss,dc=org
+objectClass: top
+objectClass: groupOfNames
+cn: JBossAdmin
+description: the JBossAdmin group
+member: uid=jduke,ou=People,dc=jboss,dc=org   
+   */
+   public void testLdapExample2() throws Exception
+   {
+      System.out.println("testLdapExample2");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke", "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample2", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      assertTrue("Principals contains jduke", subject.getPrincipals().contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+      assertFalse("Echo2 is NOT a role", roles.isMember(new SimplePrincipal("Echo2")));
+      assertFalse("TheDuke2 is NOT a role", roles.isMember(new SimplePrincipal("TheDuke2")));
+
+      lc.logout();
+   }
+   public void testLdapExample21() throws Exception
+   {
+      System.out.println("testLdapExample21");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample21", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains jduke", principals.contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+   }
+   public void testLdapExample21Encrypt() throws Exception
+   {
+      System.out.println("testLdapExample21Encrypt");
+      MBeanServer server = MBeanServerFactory.createMBeanServer("jboss");
+      JaasSecurityDomain secDomain = new JaasSecurityDomain("testLdapExample21Encrypt");
+      secDomain.setSalt("abcdefgh");
+      secDomain.setIterationCount(13);
+      secDomain.setKeyStorePass("master");
+      secDomain.setManagerServiceName(null);
+      secDomain.start();
+      ObjectName name = new ObjectName("jboss.test:service=JaasSecurityDomain,domain=testLdapExample21Encrypt");
+      server.registerMBean(secDomain, name);
+
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample21Encrypt", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains jduke", principals.contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+      MBeanServerFactory.releaseMBeanServer(server);
+   }
+   public void testLdapExample23() throws Exception
+   {
+      System.out.println("testLdapExample23");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("Java Duke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample23", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains Java Duke", principals.contains(new SimplePrincipal("Java Duke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+   }
+   public void testLdapExample22() throws Exception
+   {
+      System.out.println("testLdapExample22");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample22", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains jduke", principals.contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("Echo is a role", roles.isMember(new SimplePrincipal("Echo")));
+      assertTrue("TheDuke is a role", roles.isMember(new SimplePrincipal("TheDuke")));
+
+      lc.logout();
+   }
+   public void testLdapExample24() throws Exception
+   {
+      System.out.println("testLdapExample24");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("Java Duke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testLdapExample24", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains Java Duke", principals.contains(new SimplePrincipal("Java Duke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      assertTrue("RG2 is a role", roles.isMember(new SimplePrincipal("RG2")));
+      assertTrue("R1 is a role", roles.isMember(new SimplePrincipal("R1")));
+      assertTrue("R2 is a role", roles.isMember(new SimplePrincipal("R2")));
+      assertTrue("R3 is a role", roles.isMember(new SimplePrincipal("R3")));
+      assertFalse("R4 is NOT a role", roles.isMember(new SimplePrincipal("R4")));
+      assertTrue("R5 is a role", roles.isMember(new SimplePrincipal("R5")));
+
+      lc.logout();
+   }
+
+   /* JBAS-3312 testcase
+dn: DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+
+dn: ou=People,dc=uz,dc=kuleuven,dc=ac,dc=be
+objectClass: organizationalUnit
+ou: People
+
+dn: CN=jduke,ou=People,dc=uz,dc=kuleuven,dc=ac,dc=be
+memberOf: ou=People,dc=uz,dc=kuleuven,dc=ac,dc=be
+objectClass: top
+objectClass: person
+objectClass: organizationalPerson
+objectClass: user
+cn: JDuke
+name: Java Duke
+sn: TheDuke
+sAMAccountName: jduke
+userPrincipalName: jduke at jboss.org
+userPassword: theduke
+
+dn: OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+objectClass: organizationalUnit
+objectClass: orgUnitEx
+ou: Groups
+objectCategory: CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=uz,DC=kuleuven,DC=ac,DC=be
+
+
+dn: OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+objectClass: organizationalUnit
+objectClass: orgUnitEx
+ou: Informatiesystemen
+objectCategory: CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=uz,DC=kuleuven,DC=ac,DC=be
+
+
+dn: CN=inf_map_informatiesystemen_lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+objectClass: group
+cn: inf_map_informatiesystemen_lijst
+member: CN=inf_map_vmware_Lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+member: CN=inf_map_carenet_Lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+sAMAccountName: inf_map_informatiesystemen_lijst
+objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=uz,DC=kuleuven,DC=ac,DC=be
+
+
+dn: CN=inf_map_vmware_Lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+objectClass: group
+cn: inf_map_vmware_Lijst
+description: \\uz\data\Admin\VMWare Lijst
+member: CN=inf_map_vmware_iso_S,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+member: CN=inf_map_vmware_iso_L,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+memberOf: CN=inf_map_informatiesystemen_lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+sAMAccountName: inf_map_vmware_Lijst
+objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=uz,DC=kuleuven,DC=ac,DC=be
+
+
+dn: CN=inf_map_vmware_iso_S,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+objectClass: top
+objectClass: group
+cn: inf_map_vmware_iso_S
+description: \\uz\data\Admin\VMWare\ISO Schrijven
+member: CN=markv,OU=People,DC=uz,DC=kuleuven,DC=ac,DC=be
+member: CN=jduke,OU=People,DC=uz,DC=kuleuven,DC=ac,DC=be
+memberOf: CN=inf_map_informatiesystemen_lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+memberOf: CN=inf_map_vmware_Lijst,OU=Informatiesystemen,OU=Groups,DC=uz,DC=kuleuven,DC=ac,DC=be
+sAMAccountName: inf_map_vmware_iso_S
+objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=uz,DC=kuleuven,DC=ac,DC=be
+    */
+   public void testJBAS3312() throws Exception
+   {
+      System.out.println("testJBAS3312");
+      UsernamePasswordHandler handler = new UsernamePasswordHandler("jduke",
+         "theduke".toCharArray());
+      LoginContext lc = new LoginContext("testJBAS3312", handler);
+      lc.login();
+
+      Subject subject = lc.getSubject();
+      System.out.println("Subject: "+subject);
+
+      Set groups = subject.getPrincipals(Group.class);
+      Set principals = subject.getPrincipals();
+      assertTrue("Principals contains Java Duke", principals.contains(new SimplePrincipal("jduke")));
+      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
+      Group roles = (Group) groups.iterator().next();
+      Enumeration names = roles.members();
+      while( names.hasMoreElements() )
+      {
+         System.out.println(names.nextElement());
+      }
+      assertTrue("inf_map_vmware_iso_S is a role", roles.isMember(new SimplePrincipal("inf_map_vmware_iso_S")));
+      assertTrue("inf_map_informatiesystemen_lijst is a role", roles.isMember(new SimplePrincipal("inf_map_informatiesystemen_lijst")));
+      assertTrue("inf_map_vmware_Lijst is a role", roles.isMember(new SimplePrincipal("inf_map_vmware_Lijst")));
+
+      lc.logout();
+   }
+
+   public static void main(java.lang.String[] args)
+   {
+      System.setErr(System.out);
+      TestSuite suite = new TestSuite(LoginModulesTestCase.class);
+      junit.textui.TestRunner.run(suite);
+   }
+
+}




More information about the jboss-cvs-commits mailing list