[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>
+ * <mbean code="org.jboss.security.jce.JCEProviderService"
+ * name="Security:service=JCEProviderService">
+ * <attribute name="JceProviders">
+ * <providers>
+ * <provider class="org.bouncycastle.jce.provider.BouncyCastleProvider" position="3"/>
+ * <provider class="cryptix.provider.Cryptix"/>
+ * </providers>
+ * </attribute>
+ * </mbean>
+ * </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