Initial Contribution
Signed-off-by: Vinay Vishal <vinay.vishal@oracle.com>
diff --git a/nucleus/security/core/exclude.xml b/nucleus/security/core/exclude.xml
new file mode 100644
index 0000000..25744ca
--- /dev/null
+++ b/nucleus/security/core/exclude.xml
@@ -0,0 +1,46 @@
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<FindBugsFilter>
+ <!--
+ Need to keep both method getUsername in
+ com.sun.appserv.security.AppservPasswordLoginModule
+ and method getUserName in
+ com.sun.enterprise.security.GUILoginDialog
+ with names differing only in case, for compatibility.
+ -->
+ <Match>
+ <Class name="com.sun.appserv.security.AppservPasswordLoginModule"/>
+ <Method name="getUsername"/>
+ <Bug pattern="NM_CONFUSING"/>
+ </Match>
+
+ <!--
+ These public fields of SecurityContext are set and read by code in
+ other modules.
+ -->
+ <Match>
+ <Class name="com.sun.enterprise.common.iiop.security.SecurityContext"/>
+ <Or>
+ <Field name="authcls"/>
+ <Field name="identcls"/>
+ <Field name="subject"/>
+ </Or>
+ <Bug pattern="UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD"/>
+ </Match>
+</FindBugsFilter>
diff --git a/nucleus/security/core/osgi.bundle b/nucleus/security/core/osgi.bundle
new file mode 100644
index 0000000..4624464
--- /dev/null
+++ b/nucleus/security/core/osgi.bundle
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+-exportcontents: \
+ com.iplanet.ias.security.auth.login; \
+ com.sun.enterprise.security; \
+ com.sun.enterprise.security.auth; \
+ com.sun.enterprise.security.audit; \
+ com.sun.enterprise.security.auth.login; \
+ com.sun.enterprise.security.factory; \
+ com.iplanet.ias.security.auth.realm; \
+ com.sun.enterprise.security.auth.realm; \
+ com.sun.enterprise.security.auth.realm.certificate; \
+ com.sun.enterprise.security.auth.realm.file; \
+ com.sun.enterprise.security.auth.realm.ldap; \
+ com.sun.enterprise.security.auth.realm.solaris; \
+ com.sun.enterprise.security.util; \
+ com.sun.enterprise.common.iiop.security; \
+ com.sun.enterprise.security.auth.digest.api; \
+ com.sun.enterprise.security.auth.login.common; \
+ com.sun.enterprise.security.common; \
+ com.sun.logging.enterprise.system.core.security; \
+ com.sun.enterprise.security.ssl; version=${project.osgi.version}
+Bundle-NativeCode: \
+ libsolsparcauth.so ; \
+ osname=SunOS ; \
+ osname=Solaris ; \
+ processor=sparc , \
+ libsolx86auth.so ; \
+ osname=SunOS ; \
+ osname=Solaris ; \
+ processor=x86 , \
+ *
+# dependent flashlight package resolved at runtime
+DynamicImport-Package: org.glassfish.flashlight.provider
diff --git a/nucleus/security/core/pom.xml b/nucleus/security/core/pom.xml
new file mode 100644
index 0000000..c541dc5
--- /dev/null
+++ b/nucleus/security/core/pom.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.main.security</groupId>
+ <artifactId>nucleus-security</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>security</artifactId>
+ <packaging>glassfish-jar</packaging>
+
+ <name>Security Core Classes</name>
+
+ <developers>
+ <developer>
+ <id>kumarjayanti</id>
+ <name>V B Kumar Jayanti</name>
+ <organization>Oracle, Inc.</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <id>nitkal</id>
+ <name>Nithya Subramanian</name>
+ <organization>Oracle, Inc.</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <properties>
+ <findbugs.exclude>${project.basedir}/exclude.xml</findbugs.exclude>
+ </properties>
+
+ <build>
+ <sourceDirectory>src/main/java</sourceDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.1</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/admin-keyfile</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/keyfile</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.jks</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/secure.seed</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/server.policy</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/login.conf</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-installed</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>solarisrealm</groupId>
+ <artifactId>libsolsparcauth</artifactId>
+ <version>1.0</version>
+ <type>so</type>
+ </artifactItem>
+ <artifactItem>
+ <groupId>solarisrealm</groupId>
+ <artifactId>libsolx86auth</artifactId>
+ <version>1.0</version>
+ <type>so</type>
+ </artifactItem>
+ </artifactItems>
+ <stripVersion>
+ true
+ </stripVersion>
+ <!--<outputDirectory>${maven.project.build.outputDirectory}</outputDirectory>-->
+ <outputDirectory>target/classes</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.admin</groupId>
+ <artifactId>config-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>common-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.security</groupId>
+ <artifactId>ssl-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.deployment</groupId>
+ <artifactId>deployment-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>internal-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>glassfish-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency> <!-- for FindBugs -->
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>simple-glassfish-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.ldapbp</groupId>
+ <artifactId>ldapbp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.external</groupId>
+ <artifactId>management-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.gmbal</groupId>
+ <artifactId>gmbal</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.annotations</groupId>
+ <artifactId>logging-annotation-processor</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/login/PasswordLoginModule.java b/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/login/PasswordLoginModule.java
new file mode 100644
index 0000000..30d72e7
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/login/PasswordLoginModule.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.iplanet.ias.security.auth.login;
+
+import com.sun.enterprise.security.BasePasswordLoginModule;
+import com.sun.enterprise.security.auth.AuthenticationStatus;
+import com.sun.enterprise.security.auth.AuthenticationStatusImpl;
+import com.sun.enterprise.security.auth.realm.Realm;
+
+import javax.security.auth.login.LoginException;
+
+/**
+ * Provided for backward compatibility with SunOne 7.0
+ * Newer implementations should extend
+ * com.sun.appserv.security.BasePasswordLoginModule
+ */
+public abstract class PasswordLoginModule extends BasePasswordLoginModule
+{
+ /**
+ * authenticateUser calls authenticate which is implemented by the implementation
+ * of this subclass
+ * @throws LoginException
+ */
+ protected final void authenticateUser() throws LoginException{
+ AuthenticationStatus as = authenticate();
+ if(as.getStatus() == as.AUTH_SUCCESS)
+ return;
+ else{
+ throw new LoginException();
+ }
+ }
+
+ @Deprecated
+ public final AuthenticationStatus commitAuthentication(String username,
+ String password,
+ Realm theRealm,
+ String[] groups)
+ {
+ return commitAuthentication(username, password.toCharArray(), theRealm, groups);
+ }
+ /** Called at the end of the authenticate method by the user
+ * @return AuthenticationStatus indicating success/failure
+ */
+ public final AuthenticationStatus commitAuthentication(String username,
+ char[] password,
+ Realm theRealm,
+ String[] groups)
+ {
+ commitUserAuthentication(groups);
+ int status = AuthenticationStatus.AUTH_SUCCESS;
+ String realm = theRealm.getName();
+ String authMethod = theRealm.getAuthType();
+ AuthenticationStatus as =
+ new AuthenticationStatusImpl(username, authMethod, realm, status);
+ return as;
+ }
+ abstract protected AuthenticationStatus authenticate() throws LoginException;
+}
diff --git a/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/realm/IASRealm.java b/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/realm/IASRealm.java
new file mode 100644
index 0000000..1f89c9e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/iplanet/ias/security/auth/realm/IASRealm.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.iplanet.ias.security.auth.realm;
+
+import com.sun.enterprise.security.BaseRealm;
+
+/**
+ * Parent class for iAS Realm classes.
+ *
+ * This class no longer implements the methods of Realm, instead it extends
+ * from BaseRealm and now is only a place holder for migration and is a
+ * candidate for deprecation.
+ * This class is provided for migration of realms written for 7.0 to 8.x
+ */
+
+public abstract class IASRealm extends BaseRealm{
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/appserv/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/appserv/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/appserv/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/AnonCredential.java b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/AnonCredential.java
new file mode 100644
index 0000000..50d5057
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/AnonCredential.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * @(#)AnonCredential.java 1.1 00/10/20
+ *
+ */
+
+package com.sun.enterprise.common.iiop.security;
+
+/**
+ * This class is part of the interface between J2EE RI and security
+ * interceptors. This class is used to assert anonymous identities.
+ *
+ * @author Sekhar Vajjhala
+ */
+
+public class AnonCredential {
+
+}
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUPName.java b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUPName.java
new file mode 100644
index 0000000..eea9862
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUPName.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.common.iiop.security;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.common.Util;
+import java.util.*;
+import java.util.logging.*;
+import com.sun.logging.*;
+
+/**
+ * This class implements the GSSAPI exported name functionality
+ * as required by CSIV2.
+ *
+ * @author Sekhar Vajjhala
+ */
+
+public class GSSUPName {
+ private static java.util.logging.Logger _logger=null;
+ static{
+ _logger=SecurityLoggerInfo.getLogger();
+ }
+ public static final char AT_CHAR = '@';
+ public static final String AT_STRING = "@";
+ public static final char ESCAPE_CHAR = '\\';
+ public static final String ESCAPE_STRING = "\\";
+
+
+ private String username; // username
+ private String realm; // realmname
+ private GSSUtilsContract gssUtils;
+
+ public GSSUPName(String username, String realm)
+ {
+
+ this.username = username;
+ this.realm = realm;
+ gssUtils = Util.getDefaultHabitat().getService(GSSUtilsContract.class);
+ }
+
+ /* Construct a GSSUPName from an exported name. This constructor
+ * is for use on the server side.
+ */
+ public GSSUPName(byte[] GSSExportedName)
+ {
+ int realm_index = 0 ; // start of realm
+ int user_index = -1 ; // start of user
+ String expname = "";
+ String name_value = "" ;
+ String name_scope = "" ;
+ byte[] exportedname = null ;
+
+ gssUtils = Util.getDefaultHabitat().getService(GSSUtilsContract.class);
+ assert(gssUtils != null);
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Attempting to create a mechanism specific name from the exported name.");
+ }
+
+ try {
+ exportedname = gssUtils.importName(gssUtils.GSSUP_MECH_OID(), GSSExportedName);
+ // extract from the "UTF8" encoding
+ expname = new String(exportedname, "UTF8");
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.iiopImportNameError , e.getLocalizedMessage());
+ }
+
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"Mechanism specific name: " + expname);
+ }
+ // Deterimine the starting indices of the username and realm name
+
+ int at_index = expname.indexOf(AT_CHAR);
+ int esc_index = expname.indexOf(ESCAPE_CHAR);
+
+ if (at_index == -1) {
+ /* scoped-username is of the form:
+ * scoped-username ::== name_value
+ */
+ name_value = expname;
+
+ } else if (esc_index == -1 ) {
+ if (at_index != 0) {
+ /* name_value is not null i.e. scoped-username is of the form:
+ * scoped-username ::= name_value@name_scope
+ */
+ name_value = expname.substring(0, at_index);
+ }
+ name_scope = expname.substring(at_index+1);
+ } else {
+ // exported name contains both AT_CHAR and ESCAPE_CHAR. Separate
+ // the username and the realm name. The start of a realm name
+ // is indicated by an AT_CHAR that is not preceded by an
+ // ESCAPE_CHAR.
+ // The username always starts at 0.
+
+ user_index = 0;
+ realm_index = 0;
+ int i = 0;
+ while ( (i = expname.indexOf(AT_CHAR, i)) != -1) {
+ if (expname.charAt(i-1) != ESCAPE_CHAR) {
+ realm_index = i;
+ break;
+ }
+ i += 1;
+ }
+ name_value = expname.substring(user_index, realm_index);
+ name_scope = expname.substring(realm_index+1);
+ }
+
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"name_value: " + name_value + " ; name_scope: " + name_scope);
+ }
+
+ if ((name_value.length() > 0) && (at_index != -1)) {
+ // remove the ESCAPE_CHAR from the username
+ StringBuilder strbuf = new StringBuilder("");
+ int starti = 0 ; // start index
+ int endi = 0 ; // end index
+
+ while ((endi = name_value.indexOf(ESCAPE_CHAR, starti)) != -1) {
+ strbuf.append(name_value.substring(starti, endi));
+ starti = endi + 1;
+ }
+ strbuf.append(name_value.substring(starti));
+ name_value = strbuf.toString();
+ }
+
+ username = name_value;
+ realm = name_scope;
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"Constructed GSSUPName ( " + toString()+ " )");
+ }
+ }
+
+ /**
+ * returns and exported name as an array of 1 or more UTF8 characters.
+ */
+ public byte[] getExportedName() {
+
+ byte[] expname = {} ;
+ byte[] expname_utf8 = null ;
+ StringTokenizer strtok ;
+
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"Going to create exported name for:" + toString());
+ }
+
+ StringBuffer strbuf = new StringBuffer("");
+
+ /* Process the username for special characters AT_CHAR and ESCAPE_CHAR */
+
+ int at_index = username.indexOf(AT_CHAR);
+ int esc_index = username.indexOf(ESCAPE_CHAR);
+
+ if ( (at_index == -1) && (esc_index == -1))
+ strbuf = new StringBuffer(username); // just copy - no processing required.
+ else {
+
+ // N.B. Order of processing is important
+
+ // Replace the ESCAPE_CHAR first
+ if (esc_index != -1) {
+ strtok = new StringTokenizer(username, ESCAPE_STRING);
+ while (strtok.hasMoreTokens()) {
+ strbuf.append(strtok.nextToken());
+ strbuf.append(ESCAPE_CHAR).append(ESCAPE_CHAR);
+ }
+ }
+
+ // Replace the AT_CHAR next
+ if (at_index != -1) {
+ strtok = new StringTokenizer(username, AT_STRING);
+ while (strtok.hasMoreTokens()) {
+ strbuf.append(strtok.nextToken());
+ strbuf.append(ESCAPE_CHAR).append(AT_CHAR);
+ }
+ }
+ }
+
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"username after processing for @ and \\: " + strbuf);
+ }
+
+ /** Do not append realm name: this ensures that we dont sent
+ "default" or "certificate" to another appserver.
+
+ // append an AT-CHAR only if realm is not null.
+ // NOTe: In the current implementation, realm will never
+ // be null. It is either "certificate" or "default".
+
+ if (realm.length() > 0) {
+ strbuf.append(AT_CHAR);
+ strbuf.append(realm);
+ }
+ **/
+
+ if(_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE,"username and realm name : " + strbuf);
+ }
+ try {
+ expname_utf8 = strbuf.toString().getBytes("UTF8");
+ assert(gssUtils != null);
+ expname = gssUtils.createExportedName(
+ gssUtils.GSSUP_MECH_OID(), expname_utf8);
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.iiopCreateExportedNameError , e.getLocalizedMessage());
+ }
+
+ if(_logger.isLoggable(Level.FINE)) {
+ assert(gssUtils != null);
+ _logger.log(Level.FINE,"GSSUPName in exported format = " + gssUtils.dumpHex(expname));
+ }
+ return expname;
+ }
+
+ public String getRealm() {
+ return realm;
+ }
+
+ public String getUser() {
+ return username;
+ }
+
+ public boolean equals(Object o) {
+ if(o instanceof GSSUPName) {
+ GSSUPName nm = (GSSUPName)o;
+ if (nm.getUser().equals(username) && nm.getRealm().equals(realm))
+ return true;
+ }
+ return false;
+ }
+
+ /* Return the hashCode. */
+ public int hashCode() {
+ return username.hashCode() + realm.hashCode();
+ }
+
+ /* String representation of the GSSUPname */
+ public String toString() {
+ String s = "Username = " + username;
+ s = s + " Realm = " + realm;
+ return s;
+ }
+
+
+ // used locally by this file for test purposes
+ private static void testGSSUP(String user, String realm)
+ {
+ GSSUPName gssname;
+ GSSUPName gssname1;
+
+ _logger.log(Level.FINE,"Running unit test for TestGSSUPName.");
+ _logger.log(Level.FINE,"Creating a GSSUPName instance");
+ gssname = new GSSUPName(user, realm);
+ _logger.log(Level.FINE,"GSSUPName : " + gssname.toString());
+ _logger.log(Level.FINE,"Obtaining an exported name form");
+ byte[] expname = gssname.getExportedName();
+ _logger.log(Level.FINE,"Creating a GSSUPName instance from exported name");
+ gssname1 = new GSSUPName(expname);
+ _logger.log(Level.FINE,"GSSUPName created from exported name: " + gssname1.toString());
+ }
+
+ public static void main(String[] args) {
+ testGSSUP("sekhar@vajjha@la@", "sun.com");
+ testGSSUP("sekhar", "sun.com");
+ testGSSUP("sekhar", "");
+ testGSSUP("", "sun.com");
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUtilsContract.java b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUtilsContract.java
new file mode 100644
index 0000000..e4d7af6
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/GSSUtilsContract.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.common.iiop.security;
+
+import java.io.IOException;
+import org.jvnet.hk2.annotations.Contract;
+import sun.security.util.ObjectIdentifier;
+
+/**
+ *
+ * @author Kumar
+ */
+@Contract
+public interface GSSUtilsContract {
+
+ public String dumpHex(byte[] octets);
+
+ public byte[] importName(ObjectIdentifier oid, byte[] externalName)
+ throws IOException;
+ public byte[] createExportedName(ObjectIdentifier oid, byte[] extName)
+ throws IOException;
+ public ObjectIdentifier GSSUP_MECH_OID();
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/SecurityContext.java b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/SecurityContext.java
new file mode 100644
index 0000000..e5452ae
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/common/iiop/security/SecurityContext.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * @(#)SecurityContext.java 1.5 00/10/24
+ */
+
+package com.sun.enterprise.common.iiop.security;
+
+
+import javax.security.auth.*;
+
+/*
+ * This interface is part of the contract between CSIV2 interceptors
+ * and the rest of J2EE RI.
+ *
+ * @author Nithya Subramanian
+ */
+
+
+/**
+ * A subject is used a container for passing the security context
+ * information in the service context field. The security context
+ * information in the subject must be stored either as a private or
+ * a public credential according to the following convention:
+ *
+ * PasswordCredential:
+ * Client authentication will be performed using the username
+ * and password in the PasswordCredential. PasswordCredential
+ * must be passed as a PrivateCredential.
+ *
+ * X500Name:
+ * DN name specified in X500Name will be asserted. X500Name must
+ * be passed as a PublicCredential.
+ *
+ * GSSUPName:
+ * Identity specified in GSSUPName will be asserted. GSSUPName must
+ * be passed as a PublicCredential.
+ *
+ * X509CertificateCredential:
+ * The certificate chain in the credential will be asserted. The
+ * credential must be passed as a PublicCredential.
+ *
+ * AnonCredential:
+ * Anonymous identity will be asserted. Credential must be passed
+ * as a PublicCredential.
+ *
+ * Class fields in the SecurityContext are used for credential selection.
+ * There are two class fields: authcls and identcls.
+ *
+ * authcls is a Class object that identifies the credential for
+ * client authentication.
+ *
+ * identcls is a Class object that identifies the credential for
+ * identity assertion.
+ *
+ * The following semantics must be observed:
+ *
+ * 1. A client authentication token is always passed as a private
+ * credential. authcls set to the class of the authentication token
+ *
+ * 2. An identity token is always passed as a public credential.
+ * identcls is set to the class of the identity token.
+ *
+ * 3. authcls is set to null if there is no client auth token
+ *
+ * 4. identcls is set to null if there is no ident token
+ *
+ * 5. There must not be more than one instance of class identified
+ * by authcls or identcls. However, there can be one instance of
+ * identcls *and* authcls (this allows both a client auth token
+ * and an identity token to be passed across the interface).
+ */
+
+public class SecurityContext {
+ public Subject subject;
+ public Class authcls;
+ public Class identcls;
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/AppCNonceCacheMap.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/AppCNonceCacheMap.java
new file mode 100644
index 0000000..bff3b3f
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/AppCNonceCacheMap.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.security.common.CNonceCache;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+
+
+
+/**
+ *
+ * @author vbkumarjayanti
+ */
+@Service
+@Singleton
+public class AppCNonceCacheMap extends HashMap<String,CNonceCache> {
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseAuditModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseAuditModule.java
new file mode 100644
index 0000000..dc42049
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseAuditModule.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * AuditModule.java
+ *
+ * Created on July 27, 2003, 11:32 PM
+ */
+
+package com.sun.enterprise.security;
+
+import java.util.Properties;
+/**
+ * Base class that should be extended by all classes that wish to provide their
+ * own Audit support.
+ * @author Harpreet Singh
+ * @version
+ */
+public abstract class BaseAuditModule {
+ protected Properties props = null;
+ /**
+ * Method is invoked at server startup, during AuditModule initialization.
+ * If method returns without any exception then S1AS assumes that the module
+ * is ready to serve any requests.
+ * @param props the properties for the AuditModule. These properties are
+ * defined in the domain.xml
+ */
+ public void init(Properties props) {
+ this.props = props;
+ }
+
+ /**
+ * Invoked post authentication request for a user in a given realm
+ * @param user username for whom the authentication request was made
+ * @param realm the realm name under which the user is authenticated.
+ * @param success the status of the authentication
+ */
+ public void authentication(String user, String realm, boolean success) {
+ }
+
+ /**
+ * Invoked upon completion of the server startup
+ */
+ public void serverStarted() {
+ }
+
+ /**
+ * Invoked upon completion of the server shutdown
+ */
+ public void serverShutdown() {
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseCertificateLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseCertificateLoginModule.java
new file mode 100644
index 0000000..d7a29ca
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseCertificateLoginModule.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
+import com.sun.enterprise.security.PrincipalGroupFactory;
+import com.sun.enterprise.security.PrincipalGroupFactory;
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import javax.security.auth.x500.X500Principal;
+
+import org.glassfish.internal.api.Globals;
+import org.glassfish.security.common.Group;
+
+/**
+ * Abstract base class for certificate-based login modules.
+ *
+ * <P>Subclasses need to implement the authenticateUser() method and later
+ * call commitUserAuthentication().
+ *
+ */
+public abstract class BaseCertificateLoginModule implements LoginModule {
+
+ private Subject subject;
+ /**
+ * State shared with other login modules.
+ */
+ protected Map<String, ?> _sharedState;
+ /**
+ * Options configured for this LoginModule.
+ */
+ protected Map<String, ?> _options;
+ /**
+ * System Logger.
+ */
+ protected static final Logger _logger =
+ SecurityLoggerInfo.getLogger();
+ private CallbackHandler callbackHandler;
+ private boolean success = false;
+ private String[] groups = null;
+ private boolean commitsuccess = false;
+ private X509Certificate[] certs = null;
+ private X500Principal x500Principal;
+ private String appName = null;
+
+ public final void initialize(Subject subject, CallbackHandler callbackHandler
+ , Map<String, ?> sharedState, Map<String, ?> options) {
+ this.subject = subject;
+ this._sharedState = sharedState;
+ this._options = options;
+ this.callbackHandler = callbackHandler;
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "Login module initialized: {0}"
+ , this.getClass().toString());
+ }
+ }
+
+ public final boolean login() throws LoginException {
+ //Extract the certificates from the subject.
+ extractCredentials();
+
+ // Delegate the actual authentication to subclass.
+ authenticateUser();
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "JAAS login complete.");
+ }
+ return true;
+ }
+
+ public final boolean commit() throws LoginException {
+ if (!success) {
+ return false;
+ }
+ Set<Principal> principalSet = subject.getPrincipals();
+ for (int i = 0; i < groups.length; i++) {
+ if (groups[i] != null) {
+ Group g = Globals.getDefaultHabitat().<PrincipalGroupFactory>getService(PrincipalGroupFactory.class).
+ getGroupInstance(groups[i], CertificateRealm.AUTH_TYPE);
+ principalSet.add(g);
+ }
+ groups[i] = null;
+ }
+ groups = null;
+ commitsuccess = true;
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "JAAS authentication committed.");
+ }
+ return true;
+ }
+
+ final public boolean abort() throws LoginException {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "JAAS authentication aborted.");
+ }
+
+ if (!success) {
+ return false;
+ } else if (success && !commitsuccess) {
+ // login succeeded but overall authentication failed
+ success = false;
+ for (int i = 0; i < groups.length; i++) {
+ groups[i] = null;
+ }
+ groups = null;
+ if (certs != null) {
+ for (int i = 0; i < certs.length; i++) {
+ certs[i] = null;
+ }
+ certs = null;
+ }
+ x500Principal = null;
+ } else {
+ // overall authentication succeeded and commit succeeded,
+ // but someone else's commit failed
+ logout();
+ }
+ return true;
+
+ }
+
+ final public boolean logout() throws LoginException {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "JAAS logout for: {0}", subject.toString());
+ }
+
+ subject.getPrincipals().clear();
+ subject.getPublicCredentials().clear();
+ subject.getPrivateCredentials().clear();
+
+ success = false;
+ commitsuccess = false;
+ if (groups != null) {
+ for (int i = 0; i < groups.length; i++) {
+ groups[i] = null;
+ }
+ groups = null;
+ }
+ if (certs != null) {
+ for (int i = 0; i < certs.length; i++) {
+ certs[i] = null;
+ }
+ certs = null;
+ }
+ x500Principal = null;
+ return true;
+ }
+
+ private void extractCredentials() throws LoginException {
+ // Certificates are available as a List object in the Public Credentials.
+ Set<List> creds = subject.getPublicCredentials(List.class);
+ Iterator<List> itr = creds.iterator();
+ if (!itr.hasNext()) {
+ success = false;
+ throw new LoginException("No Certificate Credential found.");
+ }
+ List certCred = itr.next();
+ if (certCred == null || certCred.isEmpty()) {
+ success = false;
+ throw new LoginException("No Certificate(s) found.");
+ }
+ try {
+ certs = (X509Certificate[]) certCred.toArray(new X509Certificate[certCred.size()]);
+ } catch (Exception ex) {
+ throw (LoginException) new LoginException("No Certificate(s) found.").initCause(ex);
+ }
+ x500Principal = certs[0].getSubjectX500Principal();
+
+ // Callback to get the application name.
+ CertificateRealm.AppContextCallback appContext = new CertificateRealm.AppContextCallback();
+ try {
+ callbackHandler.handle(new Callback[]{appContext});
+ appName = appContext.getModuleID();
+ } catch (Exception ex) {
+ }
+ }
+
+ /**
+ *
+ * <P>This is a convenience method which can be used by subclasses
+ *
+ * <P>Note that this method is called after the authentication
+ * has succeeded. If authentication failed do not call this method.
+ *
+ * This method sets the authentication status to success if the
+ * groups parameter is non-null.
+ *
+ * @param groups String array of group memberships for user (could be
+ * empty).
+ */
+ protected final void commitUserAuthentication(final String[] groups) {
+ this.groups = groups;
+ this.success = (groups != null);
+ }
+
+ /**
+ * Perform authentication decision.
+ *
+ * Method returns silently on success and returns a LoginException
+ * on failure.
+ *
+ * <p>Must be overridden to add custom functionality.
+ * @throws LoginException on authentication failure.
+ *
+ */
+ protected abstract void authenticateUser() throws LoginException;
+
+ /**
+ * Get the application name.
+ *
+ * <p> This may be useful when a single LoginModule has to handle
+ * multiple applications that use certificates.
+ *
+ * @return the application name. Non-null only for web container.
+ */
+ protected final String getAppName() {
+ return appName;
+ }
+
+ /**
+ * Get the certificate chain presented by the client.
+ *
+ * @return the certificate chain from the client.
+ */
+ protected X509Certificate[] getCerts() {
+ return certs;
+ }
+
+ /**
+ * Returns the subject (subject distinguished name) value from the
+ * first certificate, in the client certificate chain, as an
+ * <code>X500Principal</code>. If the subject value is empty, then
+ * the <code>getName()</code> method of the returned
+ * <code>X500Principal</code> object returns an empty string ("").
+ *
+ * @return an <code>X500Principal</code> representing the subject
+ * distinguished name from thr first certificate, in the
+ * client certificate chain;
+ */
+ protected X500Principal getX500Principal() {
+ return x500Principal;
+ }
+
+ /**
+ * Return the subject being authenticated.
+ *
+ * @return the subject being authenticated.
+ */
+ protected Subject getSubject() {
+ return subject;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/BasePasswordLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BasePasswordLoginModule.java
new file mode 100644
index 0000000..0580d8c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BasePasswordLoginModule.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.util.*;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import com.sun.enterprise.security.PrincipalGroupFactory;
+import com.sun.enterprise.util.i18n.StringManager;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+
+import org.glassfish.internal.api.Globals;
+import org.glassfish.security.common.PrincipalImpl;
+import org.glassfish.security.common.Group;
+import com.sun.enterprise.security.auth.login.LoginCallbackHandler;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import java.security.Principal;
+
+/**
+ * Abstract base class for password-based login modules.
+ *
+ * <P>Most login modules receive a username and password from the client
+ * (possibly through HTTP BASIC auth, or FORM, or other mechanism) and
+ * then make (or delegate) an authentication decision based on this data.
+ * This class provides common methods for such password-based login modules.
+ *
+ * <P>Subclasses need to implement the authenticateUser() method and later
+ * call commitUserAuthentication().
+ *
+ */
+
+public abstract class BasePasswordLoginModule implements LoginModule
+{
+ // The _subject, _sharedState and _options satisfy LoginModule and are
+ // shared across sub-classes
+ protected Subject _subject;
+ protected Map _sharedState;
+ protected Map _options;
+ protected String _username;
+ @Deprecated
+ protected String _password;
+ protected char[] _passwd;
+ protected Realm _currentRealm;
+
+ // the authentication status
+ protected boolean _succeeded = false;
+ protected boolean _commitSucceeded = false;
+ protected PrincipalImpl _userPrincipal;
+ protected String[] _groupsList = null;
+
+ protected static final Logger _logger =
+ SecurityLoggerInfo.getLogger();
+
+ protected final static StringManager sm =
+ StringManager.getManager(LoginCallbackHandler.class);
+ private LoginModule userDefinedLoginModule = null;
+
+ /**
+ * Initialize this login module.
+ *
+ * @param subject - the Subject to be authenticated.
+ * @param callbackHandler - a CallbackHandler for obtaining the subject
+ * username and password.
+ * @param sharedState - state shared with other configured LoginModules.
+ * @param options - options specified in the login Configuration for
+ * this particular LoginModule.
+ *
+ */
+ final public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options)
+ {
+ _subject = subject;
+ _sharedState = sharedState;
+ _options = options;
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "Login module initialized: "+
+ this.getClass().toString());
+ }
+ }
+
+
+ /**
+ * Perform login.
+ *
+ * <P>The callback handler is used to obtain authentication info
+ * for the subject and a login is attempted. This PasswordLoginModule
+ * expects to find a PasswordCredential in the private credentials
+ * of the Subject. If not present the login fails. The callback
+ * handler is ignored as it is not really relevant on the server side.
+ * Finally, the authenticateUser() method is invoked.
+ *
+ * @returns true if login succeeds, otherwise an exception is thrown.
+ * @throws LoginException Thrown if login failed, or on other problems.
+ *
+ */
+ final public boolean login() throws LoginException
+ {
+ //Extract the username and password
+ extractCredentials();
+
+ // Delegate the actual authentication to subclass.
+ authenticateUser();
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "JAAS login complete.");
+ }
+ return true;
+ }
+
+
+ /**
+ * Commit the authentication.
+ *
+ * <P>Commit is called after all necessary login modules have succeeded.
+ * It adds (if not present) a PrincipalImpl principal and a
+ * LocalCredentials public credential to the Subject.
+ *
+ * @throws LoginException If commit fails.
+ *
+ */
+ public boolean commit() throws LoginException
+ {
+ if (_succeeded == false) {
+ return false;
+ }
+
+ // Add a Principal (authenticated identity) to the Subject
+ // Assume the user we authenticated is the PrincipalImpl [RI]
+ String realm_name = _currentRealm.getName();
+ PrincipalGroupFactory factory = Globals.getDefaultHabitat().getService(PrincipalGroupFactory.class);
+ if (factory != null)
+ _userPrincipal =
+ factory.getPrincipalInstance(getUsername(),realm_name);
+ else
+ _userPrincipal = new PrincipalImpl(getUsername());
+
+ Set<Principal> principalSet = _subject.getPrincipals();
+ if (!principalSet.contains(_userPrincipal)){
+ principalSet.add(_userPrincipal);
+ }
+ /* populate the group in the subject and clean out the slate at the same
+ * time
+ */
+ for(int i = 0; i<_groupsList.length; i++){
+ if(_groupsList[i] != null){
+ Group g;
+ if (factory != null)
+ g = factory.getGroupInstance(_groupsList[i], realm_name);
+ else
+ g = new Group(_groupsList[i]);
+
+ if(!principalSet.contains(g)){
+ principalSet.add(g);
+ }
+
+ // cleaning the slate
+ _groupsList[i] = null;
+ }
+ }
+
+ // In any case, clean out state.
+ _groupsList = null;
+ setUsername(null);
+ setPassword(null);
+ setPasswordChar(null);
+ _commitSucceeded = true;
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"JAAS authentication committed.");
+ }
+ return true;
+ }
+
+
+ /**
+ * Abort the authentication process.
+ *
+ */
+ final public boolean abort() throws LoginException
+ {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"JAAS authentication aborted.");
+ }
+
+ if (_succeeded == false) {
+ return false;
+ } else if (_succeeded == true && _commitSucceeded == false) {
+ // login succeeded but overall authentication failed
+ _succeeded = false;
+ setUsername(null);
+ setPassword(null);
+ setPasswordChar(null);
+ _userPrincipal = null;
+ for(int i = 0; i < _groupsList.length; i++){
+ _groupsList[i] = null;
+ }
+ _groupsList = null;
+ } else {
+ // overall authentication succeeded and commit succeeded,
+ // but someone else's commit failed
+ logout();
+ }
+ return true;
+ }
+
+
+ /**
+ * Log out the subject.
+ *
+ */
+ final public boolean logout() throws LoginException
+ {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "JAAS logout for: " + _subject.toString());
+ }
+
+ _subject.getPrincipals().clear();
+ _subject.getPublicCredentials().clear();
+ _subject.getPrivateCredentials().clear();
+
+ _succeeded = false;
+ _commitSucceeded = false;
+ setUsername(null);
+ setPassword(null);
+ _userPrincipal = null;
+ if(_groupsList != null){
+ for (int i = 0; i < _groupsList.length; i++){
+ _groupsList[i] = null;
+ }
+ _groupsList = null;
+ }
+ return true;
+ }
+
+
+ /**
+ *
+ * <P>This is a convenience method which can be used by subclasses
+ *
+ * <P>Note that this method is called after the authentication
+ * has succeeded. If authentication failed do not call this method.
+ *
+ * Global instance field succeeded is set to true by this method.
+ *
+ * @param groups String array of group memberships for user (could be
+ * empty).
+ */
+ public final void commitUserAuthentication (final String[] groups)
+ {
+ //Copy the groups into a new array before storing it in the instance
+ String[] groupsListCopy = (groups == null) ? null : Arrays.copyOf(groups, groups.length);
+
+ _groupsList = groupsListCopy;
+ _succeeded = true;
+ }
+
+ /**
+ * @return the subject being authenticated.
+ * use case:
+ * A custom login module could overwrite commit() method, and call getSubject()
+ * to get subject being authenticated inside its commit(). Custom principal
+ * then can be added to subject. By doing this,custom principal will be stored
+ * in calling thread's security context and participate in following Appserver's
+ * authorization.
+ *
+ */
+ public Subject getSubject()
+ {
+ return _subject;
+ }
+
+ /**
+ * Method to extract container-provided username and password
+ * @throws javax.security.auth.login.LoginException
+ */
+ final public void extractCredentials() throws LoginException {
+
+ if (_subject == null) {
+ String msg = sm.getString("pwdlm.noinfo");
+ _logger.log(Level.SEVERE, msg);
+ throw new LoginException(msg);
+ }
+
+ PasswordCredential pwdCred = null;
+
+ try {
+ Iterator i = _subject.getPrivateCredentials().iterator();
+ while (i.hasNext() && pwdCred == null) {
+ Object privCred = i.next();
+ if (privCred instanceof PasswordCredential) {
+ pwdCred = (PasswordCredential) privCred;
+ }
+ }
+ } catch (Exception e) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.privateSubjectCredentialsError, e.toString());
+ }
+
+ if (pwdCred == null) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.noPwdCredentialProvidedError);
+ String msg = sm.getString("pwdlm.nocreds");
+ throw new LoginException(msg);
+ }
+
+ // Need to obtain the requested realm to get parameters.
+
+ String realm = null;
+ try {
+ realm = pwdCred.getRealm();
+ _currentRealm = Realm.getInstance(realm);
+
+ } catch (Exception e) {
+ String msg = sm.getString("pwdlm.norealm", realm);
+ _logger.log(Level.SEVERE, msg);
+ throw new LoginException(msg);
+ }
+
+ // Get username and password data from credential (ignore callback)
+
+ setUsername(pwdCred.getUser());
+ setPasswordChar(pwdCred.getPassword());
+ setPassword(new String(pwdCred.getPassword()));
+ }
+
+
+ /**
+ * Perform authentication decision.
+ *
+ * Method returns silently on success and returns a LoginException
+ * on failure.
+ * @throws LoginException on authentication failure.
+ *
+ */
+ protected abstract void authenticateUser() throws LoginException;
+
+ public void setLoginModuleForAuthentication(LoginModule userDefinedLoginModule) {
+ this.userDefinedLoginModule = userDefinedLoginModule;
+ }
+
+ /**
+ * @return the username sent by container - is made available to the custom
+ * login module using the protected _username field.
+ * Use Case: A custom login module could use the username to validate against
+ * a realm of users
+ */
+
+ public String getUsername() {
+ return _username;
+ }
+
+ /**
+ * Used for setting the username obtained from the container internally, to
+ * be made available to the custom login module implementation
+ * @param username
+ */
+ private void setUsername(String username) {
+ this._username = username;
+ }
+
+
+ /**
+ * Deprecated - password is preferred to be a char[]
+ */
+ @Deprecated
+ public String getPassword() {
+ return _password;
+ }
+
+ /**
+ * Deprecated - password is preferred to be a char[]
+ */
+ @Deprecated
+ private void setPassword(String password) {
+ this._password = password;
+ }
+
+
+
+
+ /**
+ * @return the password sent by container - is made available to the custom
+ * login module using the protected _password field.
+ * Use Case: A custom login module could use the password to validate against
+ * a custom realm of usernames and passwords
+ * Password is preferred to be a char[] instead of a string
+ */
+
+
+ public char[] getPasswordChar() {
+ return Arrays.copyOf(_passwd, _passwd.length);
+ }
+
+ /**
+ * Used for setting the password obtained from the container internally, to
+ * be made available to the custom login module implementation
+ * Password is preferred to be a char[] instead of a string
+ * @param password
+ */
+ private void setPasswordChar(char[] password) {
+ this._passwd = password;
+ }
+
+ /**
+ * @return the currentRealm - for backward compatability
+ */
+ public Realm getCurrentRealm() {
+ return _currentRealm;
+ }
+
+ /**
+ * @return the succeeded state - for backward compatability
+ */
+ public boolean isSucceeded() {
+ return _succeeded;
+ }
+
+ /**
+ * @return the commitsucceeded state - for backward compatability
+ */
+ public boolean isCommitSucceeded() {
+ return _commitSucceeded;
+ }
+
+ /**
+ * @return the UserPrincipal - for backward compatability
+ */
+ public PrincipalImpl getUserPrincipal() {
+ return _userPrincipal;
+ }
+
+ /**
+ * @return the groupList - for backward compatability
+ */
+ public String[] getGroupsList() {
+ return Arrays.copyOf(_groupsList, _groupsList.length);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseProgrammaticLoginPermission.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseProgrammaticLoginPermission.java
new file mode 100644
index 0000000..ae29788
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseProgrammaticLoginPermission.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.security.BasicPermission;
+
+
+/**
+ * Permission for using programmatic login.
+ *
+ * <P>This permission is used by ProgrammaticLogin to verify whether
+ * the invoking code has been granted the use of this interface.
+ *
+ * <P>The name of this permission is the name of the method being invoked.
+ *
+ */
+public class BaseProgrammaticLoginPermission extends BasicPermission
+{
+ public BaseProgrammaticLoginPermission(String name)
+ {
+ super(name);
+ }
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseRealm.java
new file mode 100644
index 0000000..87c8203
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/BaseRealm.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.util.*;
+
+import com.sun.enterprise.security.auth.realm.*;
+
+import com.sun.enterprise.security.util.IASSecurityException;
+import com.sun.enterprise.util.i18n.StringManager;
+
+
+/**
+ * Parent class for iAS Realm classes.
+ *
+ * <P>This class provides default implementation for most of the abstract
+ * methods in com.sun.enterprise.security.auth.realm.Realm. Since most
+ * of these abstract methods are not supported by Realms there is
+ * no need for the subclasses to implement them. The default implementations
+ * provided here generally throw an exception if invoked.
+ *
+ * @author Harpreet Singh
+ */
+public abstract class BaseRealm extends Realm
+{
+ public static final String JAAS_CONTEXT_PARAM="jaas-context";
+
+ protected static final StringManager sm =
+ StringManager.getManager(IASRealm.class);
+
+
+ /**
+ * Returns an AuthenticationHandler object which can be used to
+ * authenticate within this realm.
+ *
+ * <P>This method return null always, since AuthenticationHandlers
+ * are generally not supported by iAS realms. Subclass can override
+ * if necessary.
+ *
+ * @return An AuthenticationHandler object for this realm (always null)
+ *
+ */
+ public AuthenticationHandler getAuthenticationHandler()
+ {
+ _logger.warning("iasrealm.noauth");
+ return null;
+ }
+
+
+ /**
+ * Returns names of all the users in this particular realm.
+ *
+ * <P>This method always throws a BadRealmException since by default
+ * this operation is not supported. Subclasses which support this
+ * method can override.
+ *
+ * @return enumeration of user names (strings)
+ * @exception com.sun.enterprise.security.auth.realm.BadRealmException if realm data structures are bad
+ *
+ */
+ public Enumeration getUserNames() throws BadRealmException
+ {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+
+ /**
+ * Returns the information recorded about a particular named user.
+ *
+ * <P>This method always throws a BadRealmException since by default
+ * this operation is not supported. Subclasses which support this
+ * method can override.
+ *
+ * @param name name of the user whose information is desired
+ * @return the user object
+ * @exception com.sun.enterprise.security.auth.realm.NoSuchUserException if the user doesn't exist
+ * @exception com.sun.enterprise.security.auth.realm.BadRealmException if realm data structures are bad
+ *
+ */
+ public User getUser(String name)
+ throws NoSuchUserException, BadRealmException
+ {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+
+ /**
+ * Returns names of all the groups in this particular realm.
+ *
+ * <P>This method always throws a BadRealmException since by default
+ * this operation is not supported. Subclasses which support this
+ * method can override.
+ *
+ * @return enumeration of group names (strings)
+ * @exception com.sun.enterprise.security.auth.realm.BadRealmException if realm data structures are bad
+ *
+ */
+ public Enumeration getGroupNames()
+ throws BadRealmException
+ {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+
+ /**
+ * Refreshes the realm data so that new users/groups are visible.
+ *
+ * <P>This method always throws a BadRealmException since by default
+ * this operation is not supported. Subclasses which support this
+ * method can override.
+ *
+ * @exception com.sun.enterprise.security.auth.realm.BadRealmException if realm data structures are bad
+ *
+ */
+ public void refresh() throws BadRealmException
+ {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+ /**
+ * Adds new user to file realm. User cannot exist already.
+ *
+ * @param name User name.
+ * @param password Cleartext password for the user.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ *
+ */
+ public void addUser(String name, char[] password, String[] groupList)
+ throws BadRealmException, IASSecurityException {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+ /**
+ * Adds new user to file realm. User cannot exist already.
+ *
+ * Deprecated - User of the overloaded method with char[] password is encouraged
+ */
+ @Deprecated
+ public void addUser(String name, String password, String[] groupList)
+ throws BadRealmException, IASSecurityException {
+ addUser(name, password.toCharArray(), groupList);
+
+ }
+
+
+
+ /**
+ * Remove user from file realm. User must exist.
+ *
+ * @param name User name.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ public void removeUser(String name)
+ throws NoSuchUserException, BadRealmException {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+ /**
+ * Update data for an existing user. User must exist.
+ * Deprecated - User of the overloaded method with char[] password is encouraged
+ *
+ */
+ @Deprecated
+ public void updateUser(String name, String newName, String password,
+ String[] groups)
+ throws NoSuchUserException, BadRealmException,
+ IASSecurityException {
+ updateUser(name, newName, (password ==null)? null : password.toCharArray(), groups);
+
+ }
+
+ /**
+ * Update data for an existing user. User must exist.
+ *
+ * @param name Current name of the user to update.
+ * @param newName New name to give this user. It can be the same as
+ * the original name. Otherwise it must be a new user name which
+ * does not already exist as a user.
+ * @param password Cleartext password for the user. If non-null the user
+ * password is changed to this value. If null, the original password
+ * is retained.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ public void updateUser(String name, String newName, char[] password,
+ String[] groups)
+ throws NoSuchUserException, BadRealmException,
+ IASSecurityException {
+ String msg = sm.getString("iasrealm.notsupported");
+ throw new BadRealmException(msg);
+ }
+
+ /**
+ * @return true if the realm implementation support User Management (add,remove,update user)
+ */
+ public boolean supportsUserManagement() {
+ //false by default.
+ return false;
+ }
+
+ /**
+ * Persist the realm data to permanent storage
+ * @throws com.sun.enterprise.security.auth.realm.BadRealmException
+ */
+ public void persist() throws BadRealmException {
+ //NOOP for realms that do not support UserManagement
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/CNonceCacheFactory.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/CNonceCacheFactory.java
new file mode 100644
index 0000000..1c2b15e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/CNonceCacheFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.security.common.CNonceCache;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ *
+ * @author vbkumarjayanti
+ */
+@Contract
+public interface CNonceCacheFactory {
+ public static final String CLUSTER_NAME_PROP="cluster_name";
+ public static final String INSTANCE_NAME_PROP="instance_name";
+ public CNonceCache createCNonceCache(String appName, String clusterName,
+ String instanceName, String storeName);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/CORBAObjectPermission.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/CORBAObjectPermission.java
new file mode 100644
index 0000000..156ce15
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/CORBAObjectPermission.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.security.BasicPermission;
+
+
+/**
+ * This object represents the permission to invoke on a set of CORBA objects
+ * that are not EJBs.
+ * The name is the CORBA Object's name (currently only "*" is supported).
+ * The actions are the methods on the object.
+ *
+ * This class extends BasicPermission to support wildcard matching.
+ */
+public class CORBAObjectPermission extends BasicPermission {
+
+ public CORBAObjectPermission() {
+
+ super("*", "*");
+ }
+
+ public CORBAObjectPermission(String name) {
+
+ super("*", "*");
+
+ // currently only name "*" is supported
+ if ( !name.equals("*") ) {
+ throw new RuntimeException("CORBAObjectPermission name must be *");
+ }
+ }
+
+ public CORBAObjectPermission(String name, String actions) {
+
+ super("*", actions);
+
+ // currently only name "*" is supported
+ if ( !name.equals("*") ) {
+ throw new RuntimeException("CORBAObjectPermission name must be *");
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ContainerSecurityLifecycle.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ContainerSecurityLifecycle.java
new file mode 100644
index 0000000..50c7e69
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ContainerSecurityLifecycle.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.jvnet.hk2.annotations.Contract;
+
+@Contract
+public interface ContainerSecurityLifecycle {
+ public void onInitialization();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/EjbSecurityPolicyProbeProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/EjbSecurityPolicyProbeProvider.java
new file mode 100644
index 0000000..dc860c7
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/EjbSecurityPolicyProbeProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.external.probe.provider.annotations.Probe;
+import org.glassfish.external.probe.provider.annotations.ProbeParam;
+import org.glassfish.external.probe.provider.annotations.ProbeProvider;
+
+
+@ProbeProvider(moduleProviderName="glassfish",moduleName="security", probeProviderName="ejbpolicy")
+public class EjbSecurityPolicyProbeProvider {
+
+ @Probe(name="policyCreationEvent")
+ public void policyCreationEvent(
+ @ProbeParam("contextId") String contextId ) {}
+
+ @Probe(name = "policyCreationStartedEvent")
+ public void policyCreationStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "policyCreationEndedEvent")
+ public void policyCreationEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/EmbeddedSecurity.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/EmbeddedSecurity.java
new file mode 100644
index 0000000..868e3e9
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/EmbeddedSecurity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.hk2.api.ServiceLocator;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * Utility contact to copy the security related config files
+ * from the passed non-embedded instanceDir to the embedded
+ * server instance's config.
+ * This is implemented by the EmbeddedSecurityUtil class
+ *
+ * @author Nithya Subramanian
+ */
+
+@Contract
+public interface EmbeddedSecurity {
+
+ public void copyConfigFiles(ServiceLocator habitat, File fromInstanceDir, File domainXml) throws IOException, XMLStreamException;
+
+ public String parseFileName(String fullFilePath);
+
+ public boolean isEmbedded(ServerEnvironment se);
+
+ public List<String> getKeyFileNames(SecurityService securityService);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUIErrorDialog.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUIErrorDialog.java
new file mode 100644
index 0000000..a7b5457
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUIErrorDialog.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * GUIErrorDialog.java
+ * An error dialog box used for FailedLogin
+ *
+ * @author Harpreet Singh
+ * @version
+ */
+
+package com.sun.enterprise.security;
+import javax.swing.*;
+import java.awt.event.*;
+
+public class GUIErrorDialog extends javax.swing.JDialog {
+ String message;
+ /** Creates new form GUIErrorDialog */
+ public GUIErrorDialog (String message){
+ super (new JFrame (), true);
+ this.message = message;
+ initComponents ();
+ pack ();
+ }
+ /** This method is called from within the constructor to
+ * initialize the form.
+ */
+ private void initComponents() {
+ okButton = new javax.swing.JButton();
+ errorLbl = new javax.swing.JLabel();
+ okButton.setAlignmentX (CENTER_ALIGNMENT);
+ errorLbl.setAlignmentX (CENTER_ALIGNMENT);
+ getContentPane().setLayout (new javax.swing.BoxLayout (getContentPane (),BoxLayout.Y_AXIS));
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ closeDialog(evt);
+ }
+ });
+ okButton.setActionCommand("okButton");
+ okButton.setText("OK");
+ okButton.addActionListener (new ActionListener (){
+ public void actionPerformed (ActionEvent e){
+ dispose ();
+ }
+ });
+ super.addWindowListener (new WindowAdapter (){
+ public void windowClosing (WindowEvent we){
+ dispose ();
+ }
+ });
+ errorLbl.setText("Error : "+message);
+ getContentPane().add (errorLbl);
+ getContentPane().add (okButton);
+ }
+
+ /** Closes the dialog */
+ private void closeDialog(java.awt.event.WindowEvent evt) {
+ setVisible (false);
+ dispose ();
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton okButton;
+ private javax.swing.JLabel errorLbl;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUILoginDialog.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUILoginDialog.java
new file mode 100644
index 0000000..e5bdd23
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/GUILoginDialog.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+
+import com.sun.enterprise.security.ssl.SSLUtils;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.security.auth.callback.*;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+
+import java.util.logging.*;
+
+import com.sun.logging.*;
+import java.util.Arrays;
+import org.glassfish.internal.api.Globals;
+
+
+/**
+ * An implementation of a LoginDialog that presents a swing based
+ * GUI for querying username and password.
+ * @author Harish Prabandham
+ * @author Harpreet Singh
+ */
+public final class GUILoginDialog implements LoginDialog {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ private String entity;
+ private PassphraseDialog passphraseDialog;
+ private CertificateDialog certDialog;
+ private static final LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(GUILoginDialog.class);
+
+ /**
+ */
+ public GUILoginDialog () {
+ this (localStrings.getLocalString("enterprise.security.defaultEntity", "user"));
+ }
+
+ /**
+ */
+ public GUILoginDialog (String entity) {
+ this.entity = entity;
+ JFrame f = new JFrame();
+ String phrase = localStrings.getLocalString("enterprise.security.loginPhrase", "Login for ");
+ passphraseDialog = new PassphraseDialog(f, phrase + entity + ":");
+ passphraseDialog.setVisible(true);
+ }
+
+ public GUILoginDialog(String entity, Callback[] callbacks) {
+ this.entity = entity;
+ String phrase = localStrings.getLocalString("enterprise.security.loginPhrase", "Login for ");
+ JFrame f = new JFrame();
+ passphraseDialog = new PassphraseDialog(f, phrase + entity + ":", callbacks);
+ passphraseDialog.setVisible(true);
+ }
+
+
+ /**
+ * @return The username of the user.
+ */
+ public String getUserName() {
+ return passphraseDialog.username;
+ }
+
+ /**
+ *@return The password of the user in plain text...
+ */
+ public final char[] getPassword() {
+ char[] temp = passphraseDialog.passphrase;
+ return (temp == null) ? null : Arrays.copyOf(temp, temp.length);
+ }
+}
+
+
+/**
+ * Create a popup dialog box to ask for the passphrase.
+ */
+class PassphraseDialog extends JDialog
+{
+ private NameCallback nameCallback = null;;
+ private PasswordCallback passwordCallback = null;
+ private ChoiceCallback choiceCallback = null;
+ private JTextField userField;
+ private JPasswordField passField;
+ private JList choiceList;
+ private JFrame frame;
+ private JButton okButton;
+ private JButton cancelButton;
+ // buttons for keystore password
+ private JButton okForKP;
+ private JButton cancelForKP;
+
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(PassphraseDialog.class);
+ String username = "";
+ char[] passphrase = null;
+
+ private JPasswordField keystorePassword;
+ private JLabel lbl;
+ // parent panel for keystore password
+ private JPanel pnl = new JPanel (new GridLayout (2, 0));
+ // panel for buttons for keystore password
+ private JPanel bpanel = new JPanel (new FlowLayout ());
+ private JPanel kpPanel = new JPanel (new FlowLayout ());
+ private final String pnlKeyStorePassword = "Keystore Password Box";
+ private final String pnlCertificateList = "Cerificate Chooser";
+ // panel for certificate list
+ private JPanel pnl2 = new JPanel ();
+ /**
+ * Create a dialog box with a frame and title.
+ *
+ * @param frame The parent frame.
+ * @param title The dialog box title.
+ */
+ protected PassphraseDialog (JFrame frame, String title) {
+ super(frame, title, true);
+ this.frame = frame;
+ super.dialogInit();
+ initbox();
+ }
+
+ /**
+ * Create a dialog box with a frame and title.
+ *
+ * @param frame The parent frame.
+ * @param title The dialog box title.
+ */
+ protected PassphraseDialog (JFrame frame,
+ String title,
+ Callback[] callbacks) {
+
+ super(frame, title, true);
+ this.frame = frame;
+ super.dialogInit();
+
+ for(int i = 0; i < callbacks.length; i++) {
+ if(callbacks[i] instanceof NameCallback) {
+ nameCallback = (NameCallback) callbacks[i];
+ } else if(callbacks[i] instanceof PasswordCallback) {
+ passwordCallback = (PasswordCallback) callbacks[i];
+ } else if(callbacks[i] instanceof ChoiceCallback) {
+ choiceCallback = (ChoiceCallback) callbacks[i];
+ }
+ }
+ initbox();
+ }
+
+ private void initbox() {
+ GridBagLayout gridbag = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ pnl2.setLayout(gridbag);
+ getContentPane ().setLayout (new CardLayout ());
+ int gridx = 0;
+ int gridy = 0;
+
+ passField = new JPasswordField(20);
+ userField = new JTextField(20);
+ choiceList = new JList();
+
+
+ if(nameCallback != null) {
+ c.gridx = gridx++;
+ c.gridy = gridy;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(20, 10, 10, 2);
+ JLabel jl = new JLabel(nameCallback.getPrompt()+": ");
+ gridbag.setConstraints(jl, c);
+ pnl2.add(jl);
+ c.gridx = gridx++;
+ c.gridy = gridy++;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(20, 3, 10, 10);
+ userField.setText(nameCallback.getDefaultName());
+ gridbag.setConstraints(userField, c);
+ userField.selectAll();
+ pnl2.add(userField);
+ }
+
+ // passField.setEchoChar ('*');
+
+ if(passwordCallback != null) {
+ gridx = 0;
+ c.gridx = gridx++;
+ c.gridy = gridy;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(20, 10, 10, 2);
+ JLabel l = new JLabel(passwordCallback.getPrompt());
+ gridbag.setConstraints(l, c);
+ pnl2.add(l);
+ c.gridx = gridx++;
+ c.gridy = gridy++;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(20, 3, 10, 10);
+ gridbag.setConstraints(passField, c);
+ pnl2.add(passField);
+ }
+ if(choiceCallback != null) {
+ /*
+ * For getting the KeyStore Password from the user
+ */
+ lbl = new JLabel
+ (localStrings.getLocalString
+ ("enterprise.security.keystore",
+ "Enter the KeyStore Password "));
+ // adding the password field
+ keystorePassword = new JPasswordField (20);
+ kpPanel.add (lbl);
+ kpPanel.add (keystorePassword);
+ /* get the keystore password */
+ final SSLUtils sslUtils = Globals.get(SSLUtils.class);
+ // ok button For keystore password
+ okForKP = new
+ JButton(localStrings.getLocalString
+ ( "enterprise.security.ok", " OK "));
+ okForKP.setActionCommand ("ok");
+
+ okForKP.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ char[] passKPFromUser = keystorePassword.getPassword();
+ if (sslUtils.verifyMasterPassword(passKPFromUser)) {
+ okForKP.setEnabled (false);
+ cancelForKP.setEnabled (false);
+ keystorePassword.setEditable (false);
+ CardLayout cl = (CardLayout) (getContentPane ()).getLayout ();
+ cl.show (getContentPane (), pnlCertificateList);
+ } else {
+ String errmessage = localStrings.getLocalString("enterprise.security.IncorrectKeystorePassword","Incorrect Keystore Password");
+ GUIErrorDialog guierr = new GUIErrorDialog(errmessage);
+ guierr.setVisible(true);
+ }
+ Arrays.fill(passKPFromUser, ' ');
+ }
+ });
+
+ cancelForKP = new
+ JButton (localStrings.getLocalString
+ ( "enterprise.security.cancel", "Cancel"));
+
+ cancelForKP.setActionCommand ("cancel");
+ cancelForKP.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ if (choiceCallback != null)
+ choiceCallback.setSelectedIndex (-1);
+ frame.dispose();
+ }
+ }
+ );
+ bpanel.add (okForKP);
+ bpanel.add (cancelForKP);
+ pnl.add (kpPanel);
+ pnl.add (bpanel);
+ // Adding the certificate lists.
+ gridx = 0;
+ c.gridx = gridx++;
+ c.gridy = gridy;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(20, 10, 10, 2);
+ JLabel l = new JLabel(choiceCallback.getPrompt());
+ gridbag.setConstraints(l, c);
+ pnl2.add(l);
+ c.gridx = gridx++;
+ c.gridy = gridy++;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(20, 3, 10, 10);
+
+ String[] choices = choiceCallback.getChoices();
+ choiceList.setListData(choices);
+
+ gridbag.setConstraints(choiceList, c);
+ pnl2.add(choiceList);
+ }
+
+ okButton = new
+ JButton(localStrings.getLocalString
+ ( "enterprise.security.ok", " OK "));
+ // XXX I18N
+ okButton.setActionCommand ("ok");
+ okButton.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ username = userField.getText();
+ if(username.trim().length() > 0)
+ nameCallback.setName(username);
+ if(passwordCallback != null) {
+ char[] pass = passField.getPassword();
+ //if(passphrase.trim().length() > 0) {
+ passwordCallback.setPassword(pass);
+ //}
+ }
+ if(choiceCallback != null) {
+ int idx = choiceList.getSelectedIndex();
+ if(idx != -1)
+ choiceCallback.setSelectedIndex(idx);
+ }
+ frame.dispose();
+ }
+ }
+
+ );
+
+ cancelButton = new JButton
+ (localStrings.getLocalString
+ ( "enterprise.security.cancel", "Cancel"));
+ cancelButton.setActionCommand ("cancel");
+ cancelButton.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ if (choiceCallback!=null) {
+ choiceCallback.setSelectedIndex (-1);
+ } else {
+ username = null;
+ if (passphrase != null) {
+ Arrays.fill(passphrase, ' ');
+ }
+ frame.dispose();
+ }
+ }
+ }
+ );
+
+ super.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent we) {
+ //System.out.println("IN WINDOW CLOSING");
+ //_logger.log(Level.FINE,"IN WINDOW CLOSING");
+ // send a fail back
+ if (choiceCallback != null)
+ choiceCallback.setSelectedIndex (-1);
+ frame.dispose();
+ }
+ });
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(gridbag);
+ c.insets = new Insets(5,0,5,15);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.NONE;
+ gridbag.setConstraints(okButton, c);
+ buttonPanel.add(okButton);
+ c.gridx = 2;
+ c.insets = new Insets(5,15,5,0);
+ gridbag.setConstraints(cancelButton, c);
+ buttonPanel.add(cancelButton);
+
+ c.gridx = 0;
+ c.gridy = gridy++;
+ c.gridwidth = 2;
+ c.insets = new Insets(0,0,5,0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.WEST;
+ gridbag.setConstraints(buttonPanel, c);
+ pnl2.add(buttonPanel);
+ getContentPane ().add (pnl, pnlKeyStorePassword);
+ getContentPane ().add (pnl2, pnlCertificateList);
+ CardLayout cl = (CardLayout) (getContentPane ()).getLayout ();
+ if (choiceCallback != null){
+ /* first get the password to the keystore */
+ cl.show (getContentPane (), pnlKeyStorePassword);
+ } else {
+ cl.show (getContentPane (), pnlCertificateList);
+ }
+ pack ();
+ setSize (getPreferredSize ());
+ }
+
+}
+
+/**
+ * Create a popup dialog box to ask for the passphrase.
+ */
+class CertificateDialog extends JDialog
+{
+ private JTextField userField;
+ private JList certList;
+ private JFrame frame;
+ private JButton okButton;
+ private JButton cancelButton;
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CertificateDialog.class);
+ String username = "";
+ char[] passphrase = new char[0];
+
+ /**
+ * Create a dialog box with a frame and title.
+ *
+ * @param frame The parent frame.
+ * @param title The dialog box title.
+ */
+ protected CertificateDialog (JFrame frame, String title) {
+ super(frame, title, true);
+ this.frame = frame;
+ super.dialogInit();
+ initbox();
+ }
+
+ private void initbox() {
+ GridBagLayout gridbag = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ getContentPane().setLayout(gridbag);
+
+ int gridx = 0;
+ int gridy = 0;
+
+ String[] list = null;
+ /**/
+ list = new String[5];
+ list[0] = "foo";
+ list[1] = "bar";
+ list[2] = "abc";
+ list[3] = "def";
+ list[4] = "ghi";
+ /**/
+
+ certList = new JList(list);
+ userField = new JTextField(20);
+
+ c.gridx = gridx++;
+ c.gridy = gridy;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(20, 10, 10, 2);
+ JLabel jl = new JLabel(localStrings.getLocalString("enterprise.security.login.username",
+ "Enter username:"));
+ gridbag.setConstraints(jl, c);
+ getContentPane().add(jl);
+ c.gridx = gridx++;
+ c.gridy = gridy++;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(20, 3, 10, 10);
+ gridbag.setConstraints(userField, c);
+ getContentPane().add(userField);
+
+ gridx = 0;
+ c.gridx = gridx++;
+ c.gridy = gridy;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(20, 10, 10, 2);
+ JLabel l = new JLabel(localStrings.getLocalString("enterprise.security.login.password",
+ "Select a certificate:"));
+ gridbag.setConstraints(l, c);
+ getContentPane().add(l);
+ c.gridx = gridx++;
+ c.gridy = gridy++;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(20, 3, 10, 10);
+ gridbag.setConstraints(certList, c);
+ getContentPane().add(certList);
+
+ okButton = new JButton(localStrings.getLocalString( "enterprise.security.ok", " OK ")); // XXX I18N
+ okButton.setActionCommand ("ok");
+ okButton.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ // System.out.println("OK Action");
+ //_logger.log(Level.FINE,"OK Action");
+ username = userField.getText();
+ //int index = certList.getSelectedIndex();
+
+ if((username.trim().length() > 0) &&
+ (passphrase.length > 0)) {
+ setVisible(false);
+ }
+ }
+ }
+ );
+
+ cancelButton = new JButton(localStrings.getLocalString( "enterprise.security.cancel", "Cancel")); // XXX I18N
+ cancelButton.setActionCommand ("cancel");
+ cancelButton.addActionListener (new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ // System.out.println("Cancel Action");
+ // _logger.log(Level.FINE,"Cancel Action");
+ // username = null;
+ // passphrase = null;
+ // setVisible(false);
+ java.awt.Toolkit.getDefaultToolkit().beep();
+ }
+ }
+ );
+
+ super.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent we) {
+ // System.out.println("IN WINDOW CLOSING");
+ // _logger.log(Level.FINE,"IN WINDOW CLOSING");
+ frame.dispose();
+ }
+ });
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(gridbag);
+ c.insets = new Insets(5,0,5,15);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.NONE;
+ gridbag.setConstraints(okButton, c);
+ buttonPanel.add(okButton);
+ c.gridx = 2;
+ c.insets = new Insets(5,15,5,0);
+ gridbag.setConstraints(cancelButton, c);
+ buttonPanel.add(cancelButton);
+
+ c.gridx = 0;
+ c.gridy = gridy++;
+ c.gridwidth = 2;
+ c.insets = new Insets(0,0,5,0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.WEST;
+ gridbag.setConstraints(buttonPanel, c);
+ getContentPane().add(buttonPanel);
+
+ pack ();
+ setSize (getPreferredSize ());
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/IRealmManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/IRealmManager.java
new file mode 100644
index 0000000..0390967
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/IRealmManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+/**
+ * This is an remote interface provided to the RealmManager
+ * This allows the realms to be updated while the server is
+ * running.
+ * @author Harpreet Singh (harpreet.singh@sun.com)
+ */
+public interface IRealmManager extends java.rmi.Remote{
+
+ /**
+ * This refreshes the realm information. This is used by
+ * a client program e.g. realmtool. The client manipulates
+ * the realm information and then calls this method. This then
+ * updates the realm information in an already running server.
+ * If the server is not running the call should not be made.
+ * This interface is obtained by looking up the <i>RealmManager</>
+ * from the Naming service.
+ * @param String realmName
+ */
+ public void refreshRealms(String realmName)
+ throws java.rmi.RemoteException;
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LocalStrings.properties
new file mode 100644
index 0000000..213ed0b
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LocalStrings.properties
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+enterprise.security.defaultEntity=user
+enterprise.security.loginPhrase=Login for
+enterprise.security.username=Username:
+enterprise.security.password=Password:
+enterprise.security.ok= OK
+enterprise.security.cancel=Cancel
+enterprise.security.looking_up_authenticator=Looking up authenticator...
+enterprise.security.login_failed=Login Failed.
+enterprise.security.login.username=Enter Username
+enterprise.security.login.password=Enter Password:
+enterprise.security.audit_log_invocation=Audit Log: Invocation
+enterprise.security.failed=Failed
+enterprise.security.keystore=Enter the KeyStore Password
+enterprise.security.IncorrectKeystorePassword=Incorrect keystore password
+enterprise.security.keytool=keytool
+enterprise.security.keytooloptions=Options:
+enterprise.security.plcyload.not14=Policy class is not an instance of java.security.Policy.
+enterprise.security.plcyload.not13=Policy class is not an instance of javax.security.auth.Policy.
+enterprise.security.securityutil.norolemapper=No Security RoleMapper. Role to Principal Information missing. Required to deploy Applications.
+enterprise.security.upgrade.warning=Upgrade from v2 EE to v3.1 requires manual steps. Please refer to the v3.1 Upgrade Guide for details.
+j2ee.norolemapper=Cannot instantiate the SecurityRoleMapperFactory
+j2ee.startupslow=Cannot write the seed file for fast startup. The next startup will be slow.
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginContext.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginContext.java
new file mode 100644
index 0000000..59ac3ee
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginContext.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.auth.login.common.LoginException;
+import com.sun.enterprise.security.common.AppservAccessController;
+import java.security.PrivilegedAction;
+
+import com.sun.enterprise.security.auth.login.ClientPasswordLoginModule;
+import com.sun.enterprise.security.auth.login.LoginContextDriver;
+import com.sun.enterprise.security.common.SecurityConstants;
+import java.util.logging.*;
+import com.sun.logging.*;
+
+/**
+ * This class is kept for CTS. Ideally we should move away from it.
+ * The login can be done via the following call:
+ * <pre>
+ * // Initialize the ORB.
+ * try {
+ * LoginContext lc = new LoginContext();
+ * lc.login("john", "john123");
+ * } catch (LoginException le) {
+ * le.printStackTrace();
+ * }
+ *
+ *
+ * </PRE>
+ *
+ * Ideally the login should be done with the system property -Dj2eelogin.name and -Dj2eelogin.password
+ *
+ * @author Harpreet Singh (hsingh@eng.sun.com)
+ */
+
+public final class LoginContext {
+
+ private static Logger _logger=null;
+ static{
+ _logger = SecurityLoggerInfo.getLogger();
+ }
+
+ private boolean guiAuth = false;
+
+ // declaring this different from the Appcontainer as
+ // this will be called from standalone clients.
+ public javax.security.auth.callback.CallbackHandler handler = null;
+
+ /**
+ * Creates the LoginContext with the defauly callback handler
+ */
+ public LoginContext () {
+ handler = new com.sun.enterprise.security.auth.login.LoginCallbackHandler(guiAuth);
+ }
+
+ /**
+ * Login method to login username and password
+ */
+ public void login(String user, String pass) throws LoginException{
+ final String username = user;
+ final String password = pass;
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+
+ System.setProperty(ClientPasswordLoginModule.LOGIN_NAME,
+ username);
+ System.setProperty(ClientPasswordLoginModule.LOGIN_PASSWORD,
+ password);
+
+ return null;
+ }
+ });
+ // Since this is a private api and the user is not supposed to use
+ // this. We use the default the LoginCallbackHandler.
+ LoginContextDriver.doClientLogin(SecurityConstants.USERNAME_PASSWORD,handler);
+ }
+
+ /** This method has been provided to satisfy the CTS Porting Package
+ * requirement for logging in a certificate
+ */
+ public void login(String username, byte[] authData)
+ throws LoginException{
+
+ // do nothing
+ }
+
+}
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginDialog.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginDialog.java
new file mode 100644
index 0000000..25bad63
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/LoginDialog.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+/**
+ * LoginManager needs implementations of this class for accessing the
+ * username and passwords.
+ * Implementations of LoginDialog can use either character based terminal,
+ * GUI, or any other form of querying to get hold of the username & password
+ * from the user.
+ *
+ * @author Harish Prabandham
+ */
+public interface LoginDialog {
+ /**
+ * @return The username of the user.
+ */
+ public String getUserName();
+ /**
+ *@return The password of the user in plain text...
+ */
+ public char[] getPassword();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/PolicyLoader.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/PolicyLoader.java
new file mode 100644
index 0000000..0c0ccd0
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/PolicyLoader.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.util.logging.*;
+
+//V3:Commented import com.sun.enterprise.server.ApplicationServer;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+//V3:Commented import com.sun.enterprise.config.serverbeans.ElementProperty;
+//V3:Commented import com.sun.enterprise.config.ConfigContext;
+import org.glassfish.hk2.api.IterableProvider;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.util.i18n.StringManager;
+import java.util.List;
+import org.glassfish.api.admin.ServerEnvironment;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+
+/**
+ * Loads the Default Policy File into the system.
+ *
+ * @author Harpreet Singh
+ * @author Jyri J. Virkki
+ *
+ */
+@Service
+@Singleton
+public class PolicyLoader{
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private SecurityService securityService;
+
+ @Inject
+ private IterableProvider<JaccProvider> jaccProviders;
+
+ private static Logger _logger = null;
+ static {
+ _logger = SecurityLoggerInfo.getLogger();
+ }
+ private static StringManager sm = StringManager.getManager(PolicyLoader.class);
+
+ private static final String POLICY_PROVIDER_14 =
+ "javax.security.jacc.policy.provider";
+ private static final String POLICY_PROVIDER_13 =
+ "javax.security.jacc.auth.policy.provider";
+ private static final String POLICY_CONF_FACTORY =
+ "javax.security.jacc.PolicyConfigurationFactory.provider";
+ private static final String POLICY_PROP_PREFIX =
+ "com.sun.enterprise.jaccprovider.property.";
+ private boolean isPolicyInstalled = false;
+
+
+ /**
+ * Attempts to install the policy-provider. The policy-provider
+ * element in domain.xml is consulted for the class to use. Note
+ * that if the javax.security.jacc.policy.provider system property
+ * is set it will override the domain.xml configuration. This will
+ * normally not be the case in S1AS.
+ *
+ * <P>The J2EE 1.3 property javax.security.jacc.auth.policy.provider is
+ * checked as a last resort. It should not be set in J2EE 1.4.
+ *
+ */
+ public void loadPolicy() {
+
+ if (isPolicyInstalled) {
+ _logger.log(Level.FINE,
+ "Policy already installed. Will not re-install.");
+ return;
+ }
+ // get config object
+ JaccProvider jacc = getConfiguredJaccProvider();
+ // set config properties (see method comments)
+ setPolicyConfigurationFactory(jacc);
+
+ boolean j2ee13 = false;
+
+
+ // check if system property is set
+ String javaPolicy = System.getProperty(POLICY_PROVIDER_14);
+
+ if (javaPolicy !=null) {
+ // inform user domain.xml is being ignored
+ _logger.log(Level.INFO, SecurityLoggerInfo.policyProviderConfigOverrideMsg,
+ new String[] { POLICY_PROVIDER_14, javaPolicy } );
+ } else {
+ // otherwise obtain JACC policy-provider from domain.xml
+ if (jacc != null) {
+ javaPolicy = jacc.getPolicyProvider();
+ }
+ }
+
+ if (javaPolicy == null) {
+ javaPolicy = System.getProperty(POLICY_PROVIDER_13);
+ if (javaPolicy != null) {
+ // warn user j2ee13 property is being used
+ j2ee13 = true;
+ _logger.log(Level.WARNING, SecurityLoggerInfo.policyProviderConfigOverrideWarning,
+ new String[] { POLICY_PROVIDER_13, javaPolicy} );
+ }
+ }
+
+ // now install the policy provider if one was identified
+ if (javaPolicy != null) {
+
+ try {
+ _logger.log(Level.INFO, SecurityLoggerInfo.policyLoading, javaPolicy);
+
+ //Object obj = Class.forName(javaPolicy).newInstance();
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class javaPolicyClass = loader.loadClass(javaPolicy);
+ Object obj = javaPolicyClass.newInstance();
+ if (j2ee13) {
+ // Use JDK 1.3 classes if j2ee1 3 property being used
+ if (!(obj instanceof javax.security.auth.Policy)) {
+ String msg =
+ sm.getString("enterprise.security.plcyload.not13");
+ throw new RuntimeException(msg);
+ }
+ javax.security.auth.Policy policy =
+ (javax.security.auth.Policy)obj;
+ javax.security.auth.Policy.setPolicy(policy);
+ policy.refresh();
+
+ } else {
+ // Otherwise use JDK 1.4 classes.
+ if (!(obj instanceof java.security.Policy)) {
+ String msg =
+ sm.getString("enterprise.security.plcyload.not14");
+ throw new RuntimeException(msg);
+ }
+ java.security.Policy policy = (java.security.Policy)obj;
+ java.security.Policy.setPolicy(policy);
+ //TODO: causing ClassCircularity error when SM ON and
+ //deployment use library feature and ApplibClassLoader
+ //it is likely a problem caused by the way classloading is done
+ //in this case.
+ if (System.getSecurityManager() == null) {
+ policy.refresh();
+ }
+ }
+
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.policyInstallError,
+ e.getLocalizedMessage());
+ throw new RuntimeException(e);
+ }
+ // Success.
+ _logger.fine("Policy set to: " + javaPolicy);
+ isPolicyInstalled = true;
+
+ } else {
+ // no value for policy provider found
+ _logger.warning(SecurityLoggerInfo.policyNotLoadingWarning);
+ }
+ }
+
+
+ /**
+ * Returns a JaccProvider object representing the jacc element from
+ * domain.xml which is configured in security-service.
+ *
+ * @return The config object or null on errors.
+ *
+ */
+ private JaccProvider getConfiguredJaccProvider() {
+ JaccProvider jacc = null;
+ try {
+ String name = securityService.getJacc();
+ jacc = getJaccProviderByName(name);
+ if (jacc == null) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.policyNoSuchName, name);
+ }
+ } catch (Exception e) {
+ _logger.warning(SecurityLoggerInfo.policyReadingError);
+ jacc = null;
+ }
+ return jacc;
+ }
+
+ private JaccProvider getJaccProviderByName(String name) {
+ if (jaccProviders == null || name == null) {
+ return null;
+ }
+
+ for (JaccProvider jaccProvider : jaccProviders) {
+ if (jaccProvider.getName().equals(name)) {
+ return jaccProvider;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Set internal properties based on domain.xml configuration.
+ *
+ * <P>The POLICY_CONF_FACTORY property is consumed by the jacc-api
+ * as documented in JACC specification. It's value is set here to the
+ * value given in domain.xml <i>unless</i> it is already set in which
+ * case the value is not modified.
+ *
+ * <P>Then and properties associated with this jacc provider from
+ * domain.xml are set as internal properties prefixed with
+ * POLICY_PROP_PREFIX. This is currently a workaround for bug 4846938.
+ * A cleaner interface should be adopted.
+ *
+ */
+ private void setPolicyConfigurationFactory(JaccProvider jacc) {
+
+ if (jacc == null) {
+ return;
+ }
+ // Handle JACC-specified property for factory
+ //TODO:V3 system property being read here
+ String prop = System.getProperty(POLICY_CONF_FACTORY);
+ if (prop != null) {
+ // warn user of override
+ _logger.log(Level.WARNING, SecurityLoggerInfo.policyFactoryOverride,
+ new String[] { POLICY_CONF_FACTORY, prop } );
+
+ } else {
+ // use domain.xml value by setting the property to it
+ String factory = jacc.getPolicyConfigurationFactoryProvider();
+ if (factory == null) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.policyConfigFactoryNotDefined);
+ } else {
+ System.setProperty(POLICY_CONF_FACTORY, factory);
+ }
+ }
+
+ // Next, make properties of this jacc provider available to provider
+ List<Property> props = jacc.getProperty();
+ for (Property p: props) {
+ String name = POLICY_PROP_PREFIX + p.getName();
+ String value = p.getValue();
+ _logger.finest("PolicyLoader set ["+name+"] to ["+value+"]");
+ System.setProperty(name, value);
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/PrincipalGroupFactory.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/PrincipalGroupFactory.java
new file mode 100644
index 0000000..4de3d21
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/PrincipalGroupFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.security.common.Group;
+import org.glassfish.security.common.PrincipalImpl;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * Factory for Group and Principal instances.
+ */
+@Contract
+public interface PrincipalGroupFactory {
+
+ PrincipalImpl getPrincipalInstance(String name, String realm);
+
+ Group getGroupInstance(String name, String realm);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityConfigListener.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityConfigListener.java
new file mode 100644
index 0000000..036fb60
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityConfigListener.java
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import org.jvnet.hk2.config.*;
+import org.jvnet.hk2.config.types.Property;
+
+import javax.inject.Singleton;
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Inject;
+
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+import com.sun.enterprise.config.serverbeans.AuditModule;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.MessageSecurityConfig;
+
+import com.sun.enterprise.security.audit.BaseAuditManager;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import java.beans.PropertyChangeEvent;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+import javax.inject.Named;
+import javax.security.auth.login.Configuration;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.hk2.api.PostConstruct;
+
+/**
+ *
+ * @author kumar.jayanti
+ */
+@Service
+@Singleton
+public class SecurityConfigListener implements ConfigListener, PostConstruct {
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ SecurityService securityService;
+
+ @Inject
+ private Logger logger;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @Inject
+ BaseAuditManager auditManager;
+
+ private String auditEnabled = null;
+ private String defaultRealm = null;
+ private String jacc = null;
+ private String activateDefaultP2RMapping = null;
+ private String mappedPrincipalClassName = null;
+
+ public SecurityConfigListener() {
+
+ }
+ /**
+ * Notification that @Configured objects that were injected have changed
+ *
+ * @param events list of changes
+ */
+public UnprocessedChangeEvents changed(PropertyChangeEvent[] events) {
+ // I am not so interested with the list of events, just sort who got added or removed for me.
+ ConfigSupport.sortAndDispatch(events, new Changed() {
+ /**
+ * Notification of a change on a configuration object
+ *
+ * @param type type of change : ADD mean the changedInstance was added to the parent
+ * REMOVE means the changedInstance was removed from the parent, CHANGE means the
+ * changedInstance has mutated.
+ * @param changedType type of the configuration object
+ * @param changedInstance changed instance.
+ */
+ public <T extends ConfigBeanProxy> NotProcessed changed(TYPE type, Class<T> changedType, T changedInstance) {
+ NotProcessed np = null;
+ switch(type) {
+ case ADD : logger.fine("A new " + changedType.getName() + " was added : " + changedInstance);
+ np = handleAddEvent(changedInstance);
+ break;
+
+ case CHANGE : logger.fine("A " + changedType.getName() + " was changed : " + changedInstance);
+ np = handleChangeEvent(changedInstance);
+ break;
+
+ case REMOVE : logger.fine("A " + changedType.getName() + " was removed : " + changedInstance);
+ np = handleRemoveEvent(changedInstance);
+ break;
+ }
+ return np;
+ }
+
+ private <T extends ConfigBeanProxy> NotProcessed handleAddEvent( T instance) {
+ NotProcessed np = null;
+ if(instance instanceof AuthRealm){
+ authRealmCreated((AuthRealm)instance);
+ }else if (instance instanceof JaccProvider){
+ np = new NotProcessed( "Cannot change JACC provider once installed, restart required" );
+ //inject PolicyLoader and try to call loadPolicy
+ //but policyLoader in V2 does not allow reloading of policy provider
+ //once installed. The only option is restart the server
+ }else if (instance instanceof AuditModule){
+ auditModuleCreated((AuditModule)instance);
+ }else if (instance instanceof MessageSecurityConfig){
+ // do nothing since we have a Message security config listener
+ } else if (instance instanceof SecurityService) {
+ //since everything exists the only thing that can be added
+ // in terms of Attrs is the defaultPrincipal and defaultPrinPassword
+ // but they are directly used from securityService in core/security
+ }
+ else {
+ np = new NotProcessed( "unimplemented: unknown instance: " + instance.getClass().getName() );
+ }
+ return np;
+ }
+
+ private <T extends ConfigBeanProxy> NotProcessed handleRemoveEvent(final T instance) {
+ NotProcessed np = null;
+ if(instance instanceof AuthRealm){
+ authRealmDeleted((AuthRealm)instance);
+ }else if (instance instanceof JaccProvider){
+ np = new NotProcessed( "Cannot change JACC provider once installed, restart required" );
+ //inject PolicyLoader and try to call loadPolicy
+ //but policyLoader in V2 does not allow reloading of policy provider
+ //once installed. The only option is restart the server
+ }else if (instance instanceof AuditModule){
+ auditModuleDeleted((AuditModule)instance);
+ }else if (instance instanceof MessageSecurityConfig){
+ //do nothing since we have a message security config listener
+ } else if (instance instanceof SecurityService) {
+ // The only Attrs on securityService whose removal can affect the
+ // security code are those which are stored explicitly
+ // they are getAuditEnabled, getDefaultRealm and getAuditModules
+ // not sure what the effect of removing getDefaultRealm
+ }
+ else {
+ np = new NotProcessed( "unimplemented: unknown instance: " + instance.getClass().getName() );
+ }
+ return np;
+ }
+
+ private <T extends ConfigBeanProxy> NotProcessed handleChangeEvent(final T instance) {
+ NotProcessed np = null;
+ if(instance instanceof AuthRealm){
+ authRealmUpdated((AuthRealm)instance);
+ }else if (instance instanceof JaccProvider){
+ np = new NotProcessed( "Cannot change JACC provider once installed, restart required" );
+ //inject PolicyLoader and try to call loadPolicy
+ //but policyLoader in V2 does not allow reloading of policy provider
+ //once installed. The only option is restart the server
+ }else if (instance instanceof AuditModule){
+ auditModuleUpdated((AuditModule)instance);
+ }else if (instance instanceof MessageSecurityConfig){
+ //do nothing since we have a message security config listener
+ } else if (instance instanceof SecurityService) {
+ // The only Attrs on securityService whose change in value can affect the
+ // security code are those which are stored explicitly
+ // they are getAuditEnabled, getDefaultRealm and getAuditModules
+ if (defaultRealm != null &&
+ !defaultRealm.equals(((SecurityService)instance).getDefaultRealm())) {
+ defaultRealm = ((SecurityService)instance).getDefaultRealm();
+ Realm.setDefaultRealm(defaultRealm);
+ }
+ if ((auditEnabled != null) &&
+ !auditEnabled.equals(((SecurityService)instance).getAuditEnabled())) {
+ boolean auditON = Boolean.parseBoolean(((SecurityService)instance).getAuditEnabled());
+ auditManager.setAuditOn(auditON);
+ }
+ if (!jacc.equals(((SecurityService)instance).getJacc())) {
+ np = new NotProcessed( "Cannot change JACC provider once installed, restart required" );
+ }
+ if ((mappedPrincipalClassName != null) && !mappedPrincipalClassName.equals(((SecurityService)instance).getMappedPrincipalClass())) {
+ np = new NotProcessed( "MappedPrincipalClassname changes for existing applications requires restart and redeployment" );
+ }
+ if (!activateDefaultP2RMapping.equals(((SecurityService)instance).getActivateDefaultPrincipalToRoleMapping())) {
+ np = new NotProcessed( "DefaultP2R changes for existng applications requires restart and redeployment" );
+ }
+ }
+ else {
+ np = new NotProcessed( "unimplemented: unknown instance: " + instance.getClass().getName() );
+ }
+ return np;
+ }
+ }, logger);
+ return null;
+}
+
+ /**
+ * New auth realm created.
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_CREATE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public static void authRealmCreated(AuthRealm instance){
+ try {
+ createRealm(instance);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * New auth realm created.
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_CREATE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public static void authRealmCreated(Config config, AuthRealm instance){
+ try {
+ createRealm(config, instance);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Auth realm deleted.
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_DELETE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public static void authRealmDeleted(Config config, AuthRealm instance) {
+ try {
+ //the listener firing has been unpredictable earlier
+ //after a CLI delete the listener's were not firing in time
+ //so we added explicit calls to this method from CLI
+ //now with latest builds it looks like listeners also fire
+ //causing a NoSuchRealmException
+ if (!Realm.isValidRealm(config.getName(), instance.getName())) {
+ return;
+ }
+ Realm.unloadInstance(config.getName(), instance.getName());
+ } catch (NoSuchRealmException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ /**
+ * Auth realm deleted.
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_DELETE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public static void authRealmDeleted(AuthRealm instance) {
+ try {
+ //the listener firing has been unpredictable earlier
+ //after a CLI delete the listener's were not firing in time
+ //so we added explicit calls to this method from CLI
+ //now with latest builds it looks like listeners also fire
+ //causing a NoSuchRealmException
+ if (!Realm.isValidRealm(instance.getName())) {
+ return;
+ }
+ Realm.unloadInstance(instance.getName());
+ } catch (NoSuchRealmException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Auth realm updated (attributes change).
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_UPDATE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public void authRealmUpdated(AuthRealm instance) {
+ try {
+ realmsManager.removeFromLoadedRealms(instance.getName());
+ createRealm(instance);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Auth realm updated (attributes change).
+ * It is called whenever a AuthRealmEvent with action of
+ * AuthRealmEvent.ACTION_UPDATE is received.
+ * @throws AdminEventListenerException when the listener is unable to
+ * process the event.
+ */
+ public void authRealmUpdated(Config config, AuthRealm instance) {
+ try {
+ realmsManager.removeFromLoadedRealms(config.getName(),instance.getName());
+ createRealm(config, instance);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * This method will create or replace existing realm with a new one
+ * in cache.
+ * @param event
+ * @exception for instance, BadRealmException, ConfigException,
+ * SynchronizationException
+ */
+ private static void createRealm(AuthRealm authRealm) throws Exception {
+ //authRealm cannot be null here
+ String className = authRealm.getClassname();
+ List<Property> elementProps = authRealm.getProperty();
+ Properties props = new Properties();
+ if (elementProps != null) {
+ for (Property p : elementProps) {
+ props.setProperty(p.getName(), p.getValue());
+ }
+ }
+ Realm.instantiate(authRealm.getName(), className, props);
+ Configuration.getConfiguration().refresh();
+ }
+
+ /**
+ * This method will create or replace existing realm with a new one
+ * in cache.
+ * @param event
+ * @exception for instance, BadRealmException, ConfigException,
+ * SynchronizationException
+ */
+ private static void createRealm(Config config, AuthRealm authRealm) throws Exception {
+ //authRealm cannot be null here
+ String className = authRealm.getClassname();
+ List<Property> elementProps = authRealm.getProperty();
+ Properties props = new Properties();
+ if (elementProps != null) {
+ for (Property p : elementProps) {
+ props.setProperty(p.getName(), p.getValue());
+ }
+ }
+ Realm.instantiate(authRealm.getName(), className, props, config.getName());
+ Configuration.getConfiguration().refresh();
+ }
+
+ public void postConstruct() {
+ if (securityService == null) {
+ //should never happen
+ return;
+ }
+ //the first 3 of them below are not stored anywhere and directly
+ //used from securityService instance available
+ //even defaultPrincipal and defaultPrincipalPassword is directly being
+ //read from securityService.
+ auditEnabled = securityService.getAuditEnabled();
+ defaultRealm = securityService.getDefaultRealm();
+ jacc = securityService.getJacc();
+ if(jacc == null) {
+ jacc = "default";
+ }
+ activateDefaultP2RMapping = securityService.getActivateDefaultPrincipalToRoleMapping();
+ mappedPrincipalClassName = securityService.getMappedPrincipalClass();
+
+ }
+
+ /**
+ * New audit module created.
+ * It is called whenever a AuditModuleEvent with action of
+ * AuditModuleEvent.ACTION_CREATE is received.
+ */
+ public void auditModuleCreated(AuditModule instance) {
+ try {
+ String classname = instance.getClassname();
+ List<Property> props = instance.getProperty();
+ Properties properties = new Properties();
+ if (props != null) {
+ for (Property p : props) {
+ properties.put(p.getName(), p.getValue());
+ }
+ }
+ auditManager.addAuditModule(instance.getName(), classname, properties);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Audit module deleted.
+ * It is called whenever a AuditModuleEvent with action of
+ * AuditModuleEvent.ACTION_DELETE is received.
+ */
+ public void auditModuleDeleted(AuditModule instance) {
+
+ auditManager.removeAuditModule(instance.getName());
+ }
+
+ /**
+ * Audit module updated (attributes change).
+ * It is called whenever a AuditModuleEvent with action of
+ * AuditModuleEvent.ACTION_UPDATE is received.
+ */
+ public void auditModuleUpdated(AuditModule instance) {
+ try {
+
+ List<Property> props = instance.getProperty();
+ Properties properties = new Properties();
+ if (props != null) {
+ for (Property p : props) {
+ properties.put(p.getName(), p.getValue());
+ }
+ }
+ // we don't have a way to get hold of the Old Module in V3
+ // so we would always delete and create new
+
+ auditManager.addAuditModule(instance.getName(), instance.getClassname(), properties);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContext.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContext.java
new file mode 100644
index 0000000..70d62f4
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContext.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.integration.AppServSecurityContext;
+import com.sun.enterprise.security.common.AppservAccessController;
+import com.sun.enterprise.security.common.AbstractSecurityContext;
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedAction;
+import javax.security.auth.Subject;
+
+import org.glassfish.internal.api.Globals;
+import org.glassfish.security.common.PrincipalImpl;
+import com.sun.enterprise.config.serverbeans.*;
+import com.sun.enterprise.security.auth.login.DistinguishedPrincipalCredential;
+//V3:Comment import com.sun.enterprise.server.ApplicationServer;
+import java.security.AccessController;
+import org.glassfish.api.admin.ServerEnvironment;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+* This class that extends AbstractSecurityContext that gets
+ * stored in Thread Local Storage. If the current thread creates
+ * child threads, the SecurityContext stored in the current
+ * thread is automatically propagated to the child threads.
+ *
+ * This class is used on the server side to represent the
+ * security context.
+ *
+ * Thread Local Storage is a concept introduced in JDK1.2.
+ * @see java.lang.ThreadLocal
+ * @see java.lang.InheritableThreadLocal
+ *
+ * @author Harish Prabandham
+ * @author Harpreet Singh
+ */
+@Service
+@PerLookup
+public class SecurityContext extends AbstractSecurityContext {
+
+ private static Logger _logger=null;
+ static {
+ _logger=SecurityLoggerInfo.getLogger();
+ }
+
+ private static InheritableThreadLocal<SecurityContext> currentSecCtx =
+ new InheritableThreadLocal<SecurityContext>();
+ private static SecurityContext defaultSecurityContext =
+ generateDefaultSecurityContext();
+
+ private static javax.security.auth.AuthPermission doAsPrivilegedPerm =
+ new javax.security.auth.AuthPermission("doAsPrivileged");
+
+ // Did the client log in as or did the server generate the context
+ private boolean SERVER_GENERATED_SECURITY_CONTEXT = false;
+
+
+ /* This creates a new SecurityContext object.
+ * Note: that the docs for Subject state that the internal sets
+ * (eg. the principal set) cannot be modified unless the caller
+ * has the modifyPrincipals AuthPermission. That said, there may
+ * be some value to setting the Subject read only.
+ * Note: changing the principals in the embedded subject (after
+ * construction will likely cause problem in the principal set
+ * keyed HashMaps of EJBSecurityManager.
+ * @param username The name of the user/caller principal.
+ * @param subject contains the authenticated principals and credential.
+ */
+ public SecurityContext(String userName, Subject subject) {
+ Subject s = subject;
+ if (s == null) {
+ s = new Subject();
+ if (_logger.isLoggable(Level.WARNING)) {
+ _logger.warning(SecurityLoggerInfo.nullSubjectWarning);
+ }
+ }
+ this.initiator = new PrincipalImpl(userName);
+ final Subject sub = s;
+ this.subject = (Subject)
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run() {
+ sub.getPrincipals().add(initiator);
+ return sub;
+ }
+ });
+ }
+
+ /**
+ * Create a SecurityContext with given subject having
+ * DistinguishedPrincipalCredential.
+ * This is used for JMAC environment.
+ * @param subject
+ */
+ public SecurityContext(Subject subject) {
+ if (subject == null) {
+ subject = new Subject();
+ if (_logger.isLoggable(Level.WARNING)) {
+ _logger.warning(SecurityLoggerInfo.nullSubjectWarning);
+ }
+ }
+
+ final Subject fsub = subject;
+ this.subject = subject;
+ this.initiator = (Principal)
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run() {
+ Principal prin = null;
+ for (Object obj : fsub.getPublicCredentials()) {
+ if (obj instanceof DistinguishedPrincipalCredential) {
+ DistinguishedPrincipalCredential dpc =
+ (DistinguishedPrincipalCredential) obj;
+ prin = dpc.getPrincipal();
+ break;
+ }
+ }
+ // for old auth module
+ if (prin == null) {
+ Iterator<Principal> prinIter = fsub.getPrincipals().iterator();
+ if (prinIter.hasNext()) {
+ prin = prinIter.next();
+ }
+ }
+ return prin;
+ }
+ });
+
+ postConstruct();
+ }
+
+ private void initDefaultCallerPrincipal() {
+ if (this.initiator == null) {
+ this.initiator = getDefaultCallerPrincipal();
+ }
+ }
+
+ public SecurityContext(String userName, Subject subject, String realm) {
+ Subject s = subject;
+ if (s == null) {
+ s = new Subject();
+ if (_logger.isLoggable(Level.WARNING)) {
+ _logger.warning(SecurityLoggerInfo.nullSubjectWarning);
+ }
+ }
+ PrincipalGroupFactory factory = Globals.getDefaultHabitat().getService(PrincipalGroupFactory.class);
+ if (factory!=null) {
+ this.initiator = factory.getPrincipalInstance(userName, realm);
+ }
+ final Subject sub = s;
+ this.subject = (Subject)
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run() {
+ sub.getPrincipals().add(initiator);
+ return sub;
+ }
+ });
+ }
+
+ /* private constructor for constructing default security context
+ */
+ public SecurityContext() {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "Default CTOR of SecurityContext called");
+ }
+ this.subject = new Subject();
+ // delay assignment of caller principal until it is requested
+ this.initiator = null;
+ this.setServerGeneratedCredentials();
+ // read only is only done for guest logins.
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ @Override
+ public Object run() {
+ subject.setReadOnly();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Initialize the SecurityContext and handle the unauthenticated
+ * principal case
+ */
+ public static SecurityContext init(){
+ SecurityContext sc = currentSecCtx.get();
+ if(sc == null) { // there is no current security context...
+ sc = defaultSecurityContext;
+ }
+ return sc;
+ }
+
+ public static SecurityContext getDefaultSecurityContext(){
+ //unauthen. Security Context.
+ return defaultSecurityContext;
+ }
+
+ public static Subject getDefaultSubject(){
+ //Subject of unauthen. Security Context.
+ return defaultSecurityContext.subject;
+ }
+
+ // get caller principal of unauthenticated Security Context
+ public static Principal getDefaultCallerPrincipal(){
+ synchronized(SecurityContext.class) {
+ if (defaultSecurityContext.initiator == null) {
+ String guestUser = null;
+ try {
+ guestUser = (String)
+ AppservAccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public java.lang.Object run() throws Exception {
+ SecurityService securityService = SecurityServicesUtil.getInstance().getHabitat().getService(SecurityService.class,
+ ServerEnvironment.DEFAULT_INSTANCE_NAME);
+ if(securityService==null) return null;
+ return securityService.getDefaultPrincipal();
+ }
+ });
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE,
+ SecurityLoggerInfo.defaultUserLoginError, e);
+ } finally {
+ if (guestUser == null) {
+ guestUser = "ANONYMOUS";
+ }
+ }
+ defaultSecurityContext.initiator = new PrincipalImpl(guestUser);
+ }
+ }
+ return defaultSecurityContext.initiator;
+ }
+
+ private static SecurityContext generateDefaultSecurityContext() {
+ synchronized (SecurityContext.class) {
+ try{
+ return (SecurityContext)
+ AppservAccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public java.lang.Object run() throws Exception{
+ return new SecurityContext();
+ }
+ });
+ } catch(Exception e){
+ _logger.log(Level.SEVERE,
+ SecurityLoggerInfo.defaultSecurityContextError,e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * No need to unmarshall the unauthenticated principal....
+ */
+ public static void reset(SecurityContext sc){
+ setCurrent(sc);
+ }
+
+
+ /**
+ * This method gets the SecurityContext stored in the
+ * Thread Local Store (TLS) of the current thread.
+ * @return The current Security Context stored in TLS. It returns
+ * null if SecurityContext could not be found in the current thread.
+ */
+ public static SecurityContext getCurrent() {
+ SecurityContext sc = currentSecCtx.get();
+ if (sc == null) {
+ sc = defaultSecurityContext;
+ }
+ return sc;
+ }
+
+
+ /**
+ * This method sets the SecurityContext stored in the TLS.
+ * @param sc
+ * The Security Context that should be stored in TLS.
+ * This public static method needs to be protected
+ * such that it can only be called by container code. Otherwise
+ * it can be called by application code to set its subject (which the
+ * EJB security manager will use to create a domain combiner,
+ * and then everything the ejb does will be run as the
+ * corresponding subject.
+ */
+ public static void setCurrent(SecurityContext sc) {
+
+ if (sc != null && sc != defaultSecurityContext) {
+
+ SecurityContext current = currentSecCtx.get();
+
+ if (sc != current) {
+
+ boolean permitted = false;
+
+ try {
+ java.lang.SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.fine("permission check done to set SecurityContext");
+ }
+ sm.checkPermission(doAsPrivilegedPerm);
+ }
+ permitted = true;
+ } catch (java.lang.SecurityException se) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.securityContextPermissionError, se);
+ } catch (Throwable t) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.securityContextUnexpectedError, t);
+ }
+
+ if (permitted) {
+ currentSecCtx.set(sc);
+ } else {
+ _logger.severe(SecurityLoggerInfo.securityContextNotChangedError);
+ }
+ }
+ } else {
+ currentSecCtx.set(sc);
+ }
+ }
+
+ public static void setUnauthenticatedContext() {
+ currentSecCtx.set(defaultSecurityContext);
+ }
+
+ public boolean didServerGenerateCredentials (){
+ return SERVER_GENERATED_SECURITY_CONTEXT;
+ }
+
+ private void setServerGeneratedCredentials(){
+ SERVER_GENERATED_SECURITY_CONTEXT = true;
+ }
+
+
+ /**
+ * This method returns the caller principal.
+ * This information may be redundant since the same information
+ * can be inferred by inspecting the Credentials of the caller.
+ * @return The caller Principal.
+ */
+ public Principal getCallerPrincipal() {
+ return this == defaultSecurityContext ? getDefaultCallerPrincipal() : initiator;
+ }
+
+
+ public Subject getSubject() {
+ return subject;
+ }
+
+
+ public String toString() {
+ return "SecurityContext[ " + "Initiator: " +
+ initiator + "Subject " + subject + " ]";
+ }
+
+ public Set getPrincipalSet() {
+ return subject.getPrincipals();
+ }
+
+ public void postConstruct() {
+ initDefaultCallerPrincipal();
+ }
+
+ public AppServSecurityContext newInstance(String userName, Subject subject, String realm) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SecurityContext: newInstance method called");
+ }
+ return new SecurityContext(userName, subject, realm);
+ }
+
+ public AppServSecurityContext newInstance(String userName, Subject subject) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SecurityContext: newInstance method called");
+ }
+ return new SecurityContext(userName, subject);
+ }
+
+ public void setCurrentSecurityContext(AppServSecurityContext context) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SecurityContext: setCurrentSecurityContext method called");
+ }
+ if (context == null) {
+ setCurrent(null);
+ return;
+ }
+ if (context instanceof SecurityContext) {
+ setCurrent((SecurityContext)context);
+ return;
+ }
+ throw new IllegalArgumentException("Expected SecurityContext, found " + context);
+ }
+
+ public AppServSecurityContext getCurrentSecurityContext() {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SecurityContext: getCurrent() method called");
+ }
+ return getCurrent();
+ }
+
+ public void setUnauthenticatedSecurityContext() {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SecurityContext: setUnauthenticatedSecurityContext method called");
+ }
+ setUnauthenticatedContext();
+ }
+
+ public void setSecurityContextWithPrincipal(Principal principal) {
+ SecurityContext ctx = getSecurityContextForPrincipal(principal);
+ setCurrent(ctx);
+ }
+
+ //Moved from J2EEInstanceListener.java
+ private SecurityContext getSecurityContextForPrincipal(final Principal p) {
+ if (p == null) {
+ return null;
+ } else if (p instanceof SecurityContextProxy) {
+ return ((SecurityContextProxy) p).getSecurityContext();
+ } else {
+ return AccessController.doPrivileged(new PrivilegedAction<SecurityContext>() {
+ public SecurityContext run() {
+ Subject s = new Subject();
+ s.getPrincipals().add(p);
+ return new SecurityContext(p.getName(), s);
+ }
+ });
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContextProxy.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContextProxy.java
new file mode 100644
index 0000000..a176a6e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityContextProxy.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+/**
+ * acts as a security context proxy
+ */
+public interface SecurityContextProxy {
+ SecurityContext getSecurityContext();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycle.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycle.java
new file mode 100644
index 0000000..66683f6
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycle.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.audit.AuditManager;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+import org.jvnet.hk2.annotations.Optional;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.PreDestroy;
+import org.glassfish.hk2.api.ServiceLocator;
+
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.security.common.Util;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import org.glassfish.internal.api.ServerContext;
+import org.glassfish.api.event.EventListener;
+import org.glassfish.api.event.EventTypes;
+import org.glassfish.api.event.Events;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+import org.jvnet.hk2.config.ConfigListener;
+
+/**
+ * This class extends default implementation of ServerLifecycle interface.
+ * It provides security initialization and setup for the server.
+ * @author Shing Wai Chan
+ */
+@Service
+@Singleton
+public class SecurityLifecycle implements PostConstruct, PreDestroy {
+
+ @Inject
+ private ServerContext sc;
+
+ //@Inject
+ //private RealmConfig realmConfig;
+
+ @Inject
+ private PolicyLoader policyLoader;
+
+ @Inject
+ private SecurityServicesUtil secServUtil;
+
+ @Inject
+ private Util util;
+
+ @Inject
+ private SSLUtils sslUtils;
+
+ @Inject
+ private SecurityConfigListener configListener;
+
+ @Inject
+ private ServiceLocator habitat;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @Inject @Optional
+ private ContainerSecurityLifecycle eeSecLifecycle;
+
+ private EventListener listener = null;
+
+ private static final String SYS_PROP_LOGIN_CONF = "java.security.auth.login.config";
+ private static final String SYS_PROP_JAVA_SEC_POLICY = "java.security.policy";
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ public SecurityLifecycle() {
+ try {
+
+ if (Util.isEmbeddedServer()) {
+ //If the user-defined login.conf/server.policy are set as system properties, then they are given priority
+ if (System.getProperty(SYS_PROP_LOGIN_CONF) == null) {
+ System.setProperty(SYS_PROP_LOGIN_CONF, Util.writeConfigFileToTempDir("login.conf").getAbsolutePath());
+ }
+ if (System.getProperty(SYS_PROP_JAVA_SEC_POLICY) == null) {
+ System.setProperty(SYS_PROP_JAVA_SEC_POLICY, Util.writeConfigFileToTempDir("server.policy").getAbsolutePath());
+ }
+ }
+
+ // security manager is set here so that it can be accessed from
+ // other lifecycles, like PEWebContainer
+ java.lang.SecurityManager secMgr = System.getSecurityManager();
+ if (_logger.isLoggable(Level.INFO)) {
+ if (secMgr != null) {
+ _logger.info(SecurityLoggerInfo.secMgrEnabled);
+ } else {
+ _logger.info(SecurityLoggerInfo.secMgrDisabled);
+ }
+ }
+ } catch(Exception ex) {
+ _logger.log(Level.SEVERE, "java_security.init_securitylifecycle_fail", ex);
+ throw new RuntimeException(ex.toString(), ex);
+ }
+ }
+
+ // override default
+ public void onInitialization() {
+
+ try {
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.secServiceStartupEnter);
+ }
+
+
+
+ //TODO:V3 LoginContextDriver has a static variable dependency on BaseAuditManager
+ //And since LoginContextDriver has too many static methods that use BaseAuditManager
+ //we have to make this workaround here.
+ //Commenting this since this is being handles in LoginContextDriver
+ // LoginContextDriver.AUDIT_MANAGER = secServUtil.getAuditManager();
+
+ //replaced with SharedSecureRandom API
+ //secServUtil.initSecureSeed();
+
+ // jacc
+ //registerPolicyHandlers();
+ // assert(policyLoader != null);
+ policyLoader.loadPolicy();
+
+ realmsManager.createRealms();
+ // start the audit mechanism
+ AuditManager auditManager = secServUtil.getAuditManager();
+ auditManager.loadAuditModules();
+
+ //Audit the server started event
+ auditManager.serverStarted();
+
+ // initRoleMapperFactory is in J2EEServer.java and not moved to here
+ // this is because a DummyRoleMapperFactory is register due
+ // to invocation of ConnectorRuntime.createActiveResourceAdapter
+ // initRoleMapperFactory is called after it
+ //initRoleMapperFactory();
+
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.secServiceStartupExit);
+ }
+
+ } catch(Exception ex) {
+ throw new SecurityLifecycleException(ex);
+ }
+ }
+
+
+
+/* private void registerPolicyHandlers()
+ throws javax.security.jacc.PolicyContextException {
+ PolicyContextHandler pch = PolicyContextHandlerImpl.getInstance();
+ PolicyContext.registerHandler(PolicyContextHandlerImpl.ENTERPRISE_BEAN,
+ pch, true);
+ PolicyContext.registerHandler(PolicyContextHandlerImpl.SUBJECT, pch, true);
+ PolicyContext.registerHandler(PolicyContextHandlerImpl.EJB_ARGUMENTS,
+ pch, true);
+ *//*V3 Commented: PolicyContext.registerHandler(PolicyContextHandlerImpl.SOAP_MESSAGE,
+ pch, true);
+ *//*
+ PolicyContext.registerHandler(PolicyContextHandlerImpl.HTTP_SERVLET_REQUEST,
+ pch, true);
+ PolicyContext.registerHandler(PolicyContextHandlerImpl.REUSE, pch, true);
+ }*/
+
+ @Override
+ public void postConstruct() {
+ onInitialization();
+ listener = new AuditServerShutdownListener();
+ Events events = habitat.getService(Events.class);
+ events.register(listener);
+
+ }
+
+ @Override
+ public void preDestroy() {
+ //DO Nothing ?
+ //TODO:V3 need to see if something needs cleanup
+
+ }
+
+ //To audit the server shutdown event
+ public class AuditServerShutdownListener implements EventListener {
+ @Override
+ public void event(Event event) {
+ if (EventTypes.SERVER_SHUTDOWN.equals(event.type())) {
+ secServUtil.getAuditManager().serverShutdown();
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycleException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycleException.java
new file mode 100644
index 0000000..b541342
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLifecycleException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+/**
+ *
+ *
+ */
+class SecurityLifecycleException extends RuntimeException {
+
+ public SecurityLifecycleException(Exception ex) {
+ this.initCause(ex);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLoggerInfo.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLoggerInfo.java
new file mode 100644
index 0000000..6980747
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityLoggerInfo.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.util.logging.Logger;
+import org.glassfish.logging.annotation.LogMessageInfo;
+import org.glassfish.logging.annotation.LogMessagesResourceBundle;
+import org.glassfish.logging.annotation.LoggerInfo;
+
+
+public class SecurityLoggerInfo {
+ public static final String LOGMSG_PREFIX = "NCLS-SECURITY";
+
+ @LogMessagesResourceBundle
+ public static final String SHARED_LOGMESSAGE_RESOURCE = "com.sun.enterprise.security.LogMessages";
+
+ @LoggerInfo(subsystem = "SECURITY", description = "Core Security", publish = true)
+ public static final String SECURITY_LOGGER = "javax.enterprise.system.core.security";
+ private static final Logger securityLogger = Logger.getLogger(
+ SECURITY_LOGGER, SHARED_LOGMESSAGE_RESOURCE);
+
+ public static Logger getLogger() {
+ return securityLogger;
+ }
+
+ //Common Security messages
+ @LogMessageInfo(
+ message = "Caught exception.",
+ cause ="Unknown.",
+ action ="Check the server logs and contact Oracle support.",
+ level = "WARNING")
+ public static final String securityExceptionError = LOGMSG_PREFIX + "-01000";
+
+ @LogMessageInfo(
+ message = "Java security manager is enabled.",
+ level = "INFO")
+ public static final String secMgrEnabled = LOGMSG_PREFIX + "-01001";
+
+ @LogMessageInfo(
+ message = "Java security manager is disabled.",
+ level = "INFO")
+ public static final String secMgrDisabled = LOGMSG_PREFIX + "-01002";
+
+ @LogMessageInfo(
+ message = "An I/O error occurred during copying of server config files.",
+ cause ="Copying server config files.",
+ action ="Check the server logs and contact Oracle support.",
+ level = "SEVERE")
+ public static final String ioError = LOGMSG_PREFIX + "-01004";
+
+ @LogMessageInfo(
+ message = "XML processing error occurred during copying of server config files.",
+ cause = "The XML file(s) may not be well formed.",
+ action = "Make sure the XML file(s) are well formed.",
+ level = "SEVERE")
+ public static final String xmlStreamingError = LOGMSG_PREFIX + "-01005";
+
+ // Security service messages
+ @LogMessageInfo(
+ message = "Entering Security Startup Service.",
+ level = "INFO")
+ public static final String secServiceStartupEnter = LOGMSG_PREFIX + "-01010";
+
+ @LogMessageInfo(
+ message = "Security Service(s) started successfully.",
+ level = "INFO")
+ public static final String secServiceStartupExit = LOGMSG_PREFIX + "-01011";
+
+ @LogMessageInfo(
+ message = "Error obtaining keystore and truststore files for embedded server.",
+ cause = "Saving the keystore and/or truststore to the temporary directory.",
+ action = "Check if the user.home directory is writable.",
+ level = "SEVERE")
+ public static final String obtainingKeyAndTrustStoresError = LOGMSG_PREFIX + "-01012";
+
+ @LogMessageInfo(
+ message = "An I/O error occurred while copying the security config files.",
+ cause = "Copying security files to instanceRoot/config.",
+ action = "Check the server logs and contact Oracle support.",
+ level = "WARNING")
+ public static final String copyingSecurityConfigFilesIOError = LOGMSG_PREFIX + "-01013";
+
+ @LogMessageInfo(
+ message = "An error occurred while upgrading the security config files.",
+ cause = "Upgrade security config files from a previous version.",
+ action = "Check the server logs and contact Oracle support.",
+ level = "SEVERE")
+ public static final String securityUpgradeServiceException = LOGMSG_PREFIX + "-01014";
+
+ @LogMessageInfo(
+ message = "Upgrade from v2 EE to v3.1 requires manual steps. Please refer to the v3.1 Upgrade Guide for details.",
+ cause = "Upgrade security config files from a previous version.",
+ action = "Please refer to the v3.1 Upgrade Guide for details.",
+ level = "WARNING")
+ public static final String securityUpgradeServiceWarning = LOGMSG_PREFIX + "-01015";
+
+ // General login processing messages: start 1050
+ @LogMessageInfo(
+ message = "Certificate authentication requires certificate realm.",
+ cause = "Unknown realm type.",
+ action = "Check server configuration",
+ level = "WARNING")
+ public static final String certLoginBadRealmError = LOGMSG_PREFIX + "-01050";
+
+
+ //Realms and Login Modules: start at 1100
+ @LogMessageInfo(
+ message = "Disabled realm [{0}] due to errors.",
+ cause ="No realms available.",
+ action ="Check the server logs and contact Oracle support.",
+ level = "WARNING")
+ public static final String realmConfigDisabledError = LOGMSG_PREFIX + "-01100";
+
+ @LogMessageInfo(
+ message = "No realms available. Authentication services disabled.",
+ cause ="No realms available.",
+ action ="Check the server logs and contact Oracle support.",
+ level = "SEVERE")
+ public static final String noRealmsError = LOGMSG_PREFIX + "-01101";
+
+ @LogMessageInfo(
+ message = "Error while obtaining private subject credentials: {0}",
+ cause = "Private Credentials of Subject not available.",
+ action = "Please check if the private credentials are available.",
+ level = "WARNING")
+ public static final String privateSubjectCredentialsError = LOGMSG_PREFIX + "-01104";
+
+ @LogMessageInfo(
+ message = "A PasswordCredential was required but not provided.",
+ cause = "PasswordCredential was required, but not supplied.",
+ action = "Please check if the password is provided.",
+ level = "SEVERE")
+ public static final String noPwdCredentialProvidedError = LOGMSG_PREFIX + "-01105";
+
+ @LogMessageInfo(
+ message = "Realm [{0}] of classtype [{1}] successfully created.",
+ level = "INFO")
+ public static final String realmCreated = LOGMSG_PREFIX + "-01115";
+
+ @LogMessageInfo(
+ message = "Realm [{0}] successfully updated.",
+ level = "INFO")
+ public static final String realmUpdated = LOGMSG_PREFIX + "-01117";
+
+ @LogMessageInfo(
+ message = "Realm [{0}] successfully deleted.",
+ level = "INFO")
+ public static final String realmDeleted = LOGMSG_PREFIX + "-01119";
+
+
+ // JACC and policy: start at 1140
+ @LogMessageInfo(
+ message = "Policy provider configuration overridden by property {0} with value {1}.",
+ level = "INFO")
+ public static final String policyProviderConfigOverrideMsg = LOGMSG_PREFIX + "-01140";
+
+ @LogMessageInfo(
+ message = "Requested jacc-provider [{0}] is not configured in domain.xml.",
+ level = "WARNING")
+ public static final String policyNoSuchName = LOGMSG_PREFIX + "-01141";
+
+ @LogMessageInfo(
+ message = "Error while reading policy-provider in domain.xml.",
+ level = "WARNING")
+ public static final String policyReadingError = LOGMSG_PREFIX + "-01142";
+
+ @LogMessageInfo(
+ message = "Loading policy provider {0}.",
+ level = "INFO")
+ public static final String policyLoading = LOGMSG_PREFIX + "-01143";
+
+ @LogMessageInfo(
+ message = "Error while installing policy provider: {0}.",
+ cause = "Setting the system wide policy.",
+ action = "Make sure there's sufficient permission to set the policy.",
+ level = "SEVERE")
+ public static final String policyInstallError = LOGMSG_PREFIX + "-01144";
+
+ @LogMessageInfo(
+ message = "No policy provider defined. Will use the default JDK Policy implementation.",
+ level = "WARNING")
+ public static final String policyNotLoadingWarning = LOGMSG_PREFIX + "-01145";
+
+ @LogMessageInfo(
+ message = "Policy configuration factory overridden by property {0} with value {1}",
+ level = "WARNING")
+ public static final String policyFactoryOverride = LOGMSG_PREFIX + "-01146";
+
+ @LogMessageInfo(
+ message = "Policy configuration factory not defined.",
+ level = "WARNING")
+ public static final String policyConfigFactoryNotDefined = LOGMSG_PREFIX + "-01147";
+
+ @LogMessageInfo(
+ message = "Policy provider configuration overridden by property {0} with value {1}.",
+ level = "WARNING")
+ public static final String policyProviderConfigOverrideWarning = LOGMSG_PREFIX + "-01149";
+
+ @LogMessageInfo(
+ message = "Failed to get the group names for user {0} in realm {1}: {2}.",
+ cause = "Operation now allowed",
+ action = "Check the server logs and contact Oracle support",
+ level = "WARNING")
+ public static final String invalidOperationForRealmError = LOGMSG_PREFIX + "-01150";
+
+ @LogMessageInfo(
+ message = "Failed to get the group names for user {0} in realm {1}: {2}.",
+ cause = "Obtain the group names for a nonexistent user",
+ action = "Make sure the user is valid",
+ level = "WARNING")
+ public static final String noSuchUserInRealmError = LOGMSG_PREFIX + "-01151";
+
+ @LogMessageInfo(
+ message = "ERROR: Unknown credential provided. Class: [{0}].",
+ level = "INFO")
+ public static final String unknownCredentialError = LOGMSG_PREFIX + "-05019";
+
+ @LogMessageInfo(
+ message = "Exception in getting security context.",
+ cause = "There was an exception obtaining the default security context.",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String defaultSecurityContextError = LOGMSG_PREFIX + "-05036";
+
+ @LogMessageInfo(
+ message = "Default user login error.",
+ cause = "There was an exception while authenticating the default caller principal.",
+ action = "Check the server logs and contact Oracle support.",
+ level = "SEVERE")
+ public static final String defaultUserLoginError = LOGMSG_PREFIX + "-05038";
+
+ @LogMessageInfo(
+ message = "Exception entering name and password for security.",
+ cause = "An exception occurred while processing username and password for security.",
+ action = "An exception occurred while processing username and password for security.",
+ level = "SEVERE")
+ public static final String usernamePasswordEnteringSecurityError = LOGMSG_PREFIX + "-05039";
+
+ @LogMessageInfo(
+ message = "Exception in security accesscontroller action.",
+ cause = "Running a privileged action",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String securityAccessControllerActionError = LOGMSG_PREFIX + "-05043";
+
+
+ @LogMessageInfo(
+ message = "Audit: Authentication refused for [{0}].",
+ level = "INFO")
+ public static final String auditAtnRefusedError = LOGMSG_PREFIX + "-05046";
+
+ @LogMessageInfo(
+ message = "doAsPrivileged AuthPermission required to set SecurityContext.",
+ cause = "Setting the SecurityContext in the current thread",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String securityContextPermissionError = LOGMSG_PREFIX + "-05048";
+
+ @LogMessageInfo(
+ message = "Unexpected exception while attempting to set SecurityContext.",
+ cause = "There was an unexpected exception while setting the security context.",
+ action = "Check the server logs and contact Oracle support.",
+ level = "SEVERE")
+ public static final String securityContextUnexpectedError = LOGMSG_PREFIX + "-05049";
+
+ @LogMessageInfo(
+ message = "Could not change the SecurityContext.",
+ cause = "Changing the current SecurityContext.",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String securityContextNotChangedError = LOGMSG_PREFIX + "-05050";
+
+ @LogMessageInfo(
+ message = "Subject is null.",
+ cause = "null Subject used in SecurityContext construction.",
+ action = "Make sure the Subject is not null",
+ level = "WARNING")
+ public static final String nullSubjectWarning = LOGMSG_PREFIX + "-05052";
+
+ @LogMessageInfo(
+ message = "Role mapping conflicts found in application {0}. Some roles may not be mapped.",
+ level = "INFO")
+ public static final String roleMappingConflictError = LOGMSG_PREFIX + "-05055";
+
+ @LogMessageInfo(
+ message = "Error converting certificate {0}: {1}",
+ level = "INFO")
+ public static final String convertingCertError = LOGMSG_PREFIX + "-05056";
+
+ @LogMessageInfo(
+ message = "Failed to instantiate the SecurityLifeCycle.",
+ cause = "Unknown",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String secMgrInitFailure = LOGMSG_PREFIX + "-05101";
+
+ @LogMessageInfo(
+ message = "Error enabling secure admin.",
+ cause = "Enable secure admin",
+ action = "Check your command usage",
+ level = "SEVERE")
+ public static final String enablingSecureAdminError = LOGMSG_PREFIX + "-05200";
+
+ @LogMessageInfo(
+ message = "Error disabling secure admin.",
+ cause = "Disable secure admin",
+ action = "Check your command usage",
+ level = "SEVERE")
+ public static final String disablingSecureAdminError = LOGMSG_PREFIX + "-05201";
+
+ @LogMessageInfo(
+ message = "IIOP Security - error importing a name: ${0}.",
+ cause = "Importing a name in IIOP",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String iiopImportNameError = LOGMSG_PREFIX + "-05300";
+
+ @LogMessageInfo(
+ message = "IIOP Security - error creating an exported name: ${0}.",
+ cause = "Creating an exported name in IIOP",
+ action = "Check the server logs and contact Oracle support",
+ level = "SEVERE")
+ public static final String iiopCreateExportedNameError = LOGMSG_PREFIX + "-05301";
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityManager.java
new file mode 100644
index 0000000..0de6555
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.lang.reflect.Method;
+
+import javax.security.auth.Subject;
+import org.glassfish.api.invocation.ComponentInvocation;
+
+/**
+ * This interface is used by the Container to manage access to EJBs.
+ * The container has a reference to an implementation of this
+ * interface.
+ * @author Harish Prabandham
+ */
+public interface SecurityManager {
+
+ /**
+ * @param The Invocation object containing the details of the invocation.
+ * @return true if the client is allowed to invoke the EJB, false otherwise.
+ */
+ public boolean authorize(ComponentInvocation inv);
+
+ /**
+ * @return The Principal of the client who made the current
+ * invocation.
+ */
+ public Principal getCallerPrincipal();
+
+ /**
+ * @return A boolean true/false depending on whether or not the caller
+ * has the specified role.
+ * @param The EJB developer specified "logical role".
+ */
+ public boolean isCallerInRole(String role);
+
+
+ /** This sets up the security context - if not set
+ * and does run-as related login if required
+ * @param ComponentInvocation
+ */
+ public void preInvoke (ComponentInvocation inv);
+
+ /**
+ * This method is used by the Invocation Manager to remove
+ * the run-as identity information that was set up using the
+ * preInvoke
+ * @param ComponentInvocation
+ */
+ public void postInvoke (ComponentInvocation inv);
+
+ /**
+ * Call this method to clean up all the bookeeping
+ * data-structures in the SM.
+ */
+ public void destroy();
+
+ /**
+ * This will return the subject associated with the current
+ * call. If the run as subject is in effect. It will return that
+ * subject. This is done to support the JACC specification which says
+ * if the runas principal is in effect, that principal should be used
+ * for making a component call.
+ * @return Subject the current subject. Null if this is not the
+ * runas case
+ */
+ public Subject getCurrentSubject();
+
+ /**
+ * Purge ThreadLocals held by javax.security.jacc.PolicyContext
+ */
+ public void resetPolicyContext();
+
+
+ /* This method is used by SecurityUtil runMethod to run the
+ * action as the subject encapsulated in the cuurent
+ * SecurityContext.
+ */
+
+ public Object doAsPrivileged(PrivilegedExceptionAction pea)
+ throws Throwable;
+
+ public Object invoke(Method beanClassMethod, boolean isLocal, Object o, Object[] oa)
+ throws Throwable;
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityRoleMapperFactoryGen.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityRoleMapperFactoryGen.java
new file mode 100644
index 0000000..3ba95ac
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityRoleMapperFactoryGen.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * SecurityRoleMapperFactoryGen.java
+ *
+ * Created on September 23, 2009, 12:34 PM
+ */
+
+package com.sun.enterprise.security;
+
+import java.lang.ref.WeakReference;
+import org.glassfish.deployment.common.SecurityRoleMapperFactory;
+import org.glassfish.internal.api.Globals;
+
+/**
+ *
+ * @author nasradu8
+ */
+public class SecurityRoleMapperFactoryGen {
+
+ private static WeakReference<SecurityRoleMapperFactory> securityRoleMapperFactory = new WeakReference<SecurityRoleMapperFactory>(null);
+
+ private static synchronized SecurityRoleMapperFactory _getSecurityRoleMapperFactory() {
+ if (securityRoleMapperFactory.get() == null) {
+ securityRoleMapperFactory = new WeakReference<SecurityRoleMapperFactory>(Globals.get(SecurityRoleMapperFactory.class));
+ }
+ return securityRoleMapperFactory.get();
+ }
+
+ public static SecurityRoleMapperFactory getSecurityRoleMapperFactory() {
+ if (securityRoleMapperFactory.get() != null) {
+ return securityRoleMapperFactory.get();
+ }
+ return _getSecurityRoleMapperFactory();
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityServicesUtil.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityServicesUtil.java
new file mode 100644
index 0000000..de774c5
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityServicesUtil.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.audit.AuditManager;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.api.admin.ServerEnvironment;
+import java.util.logging.Logger;
+import javax.security.auth.callback.CallbackHandler;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.api.admin.ProcessEnvironment;
+import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.api.Globals;
+
+@Service
+@Singleton
+public class SecurityServicesUtil {
+
+ private static ServiceLocator habitat = Globals.getDefaultHabitat();
+
+ private static final LocalStringManagerImpl _localStrings =
+ new LocalStringManagerImpl(SecurityServicesUtil.class);
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+ // Using SharedSecureRandom from internal-api instead.
+ // SecureRandom number used for HTTPS and IIOP/SSL.
+ // This number is accessed by iiop/IIOPSSLSocketFactory
+ // & web/security/SSLSocketFactory classes.
+ //public static final SecureRandom secureRandom = new SecureRandom();
+
+ @Inject
+ private ProcessEnvironment processEnv;
+
+ @Inject
+ private ServerEnvironment env;
+
+ @Inject
+ private AuditManager auditManager;
+
+// static {
+// secureRandom.setSeed(System.currentTimeMillis());
+// }
+
+ //the appclient CBH
+ private CallbackHandler callbackHandler;
+
+ /**
+ * replacing all of this with SharedSecureRandom
+ * So on restart, all your seed material comes from a new time that varies
+ * little from something guessable, plus something you repeat every run?
+ * Seems weak to me. Why do you want to keep the seed around?
+ * There are some situations where this might be needed,
+ * but if you're just looking for as random numbers as possible,
+ * I don't think this is not a good way to achieve it.
+ * code moved from J2EEServer.run()
+ */
+// public void initSecureSeed() {
+//
+// File secureSeedFile = null;
+// if (Util.isEmbeddedServer()) {
+// try {
+// secureSeedFile = Util.writeConfigFileToTempDir("secure.seed");
+//
+// } catch (IOException ex) {
+// String errmsg =
+// "IOException while constructing embedded config file";
+// _logger.log(Level.WARNING, errmsg);
+// }
+// } else {
+// secureSeedFile = new File(env.getConfigDirPath(), "secure.seed");
+// }
+//
+// // read the secure random from the file
+// long seed = readSecureSeed(secureSeedFile);
+// secureRandom.setSeed(seed);
+// // generate a new one for the next startup
+// seed = secureRandom.nextLong();
+// writeSecureSeed(secureSeedFile, seed);
+// secureSeedFile = null;
+// }
+
+ /** read the secure random number from the file.
+ * If the seed is not present, the default expensive SecureRandom seed
+ * generation algorithm is invoked to return a new seed number
+ * @param fname the file to be read - here secure.seed file.
+ */
+// private long readSecureSeed(File fname) {
+// byte[] seed;
+// try {
+// BufferedReader fis = new BufferedReader(new FileReader(fname));
+// try {
+// String line = fis.readLine();
+// fis.close();
+// // returning a long value.
+// Long lseed = new Long(line);
+// return lseed.longValue();
+// } catch (IOException e) {
+// if (fis != null) {
+// fis.close();
+// }
+// }
+// } catch (Throwable e) { // IASRI 4666401 if all fails just create new
+// }
+// // BEGIN IASRI 4703002
+// // In order to work around JVM bug 4709460 avoid internal seeding.
+// // (Call setSeed again (see static block) to attempt to add some
+// // minimal randomness; setSeed calls are cumulative)
+//
+// secureRandom.setSeed(System.currentTimeMillis());
+// long newSeed = secureRandom.nextLong();
+// return newSeed;
+// }
+
+ /** write the new secure seed to the secure.seed file to speed up
+ * startup the next time the server is started.
+ * @param fname secure.seed file
+ * @param seed seed the value of the 8 byte seed.
+ */
+// private void writeSecureSeed(File fname, long seed) {
+// try {
+// FileOutputStream fos = new FileOutputStream(fname);
+// String sseed = Long.toString(seed);
+// fos.write(sseed.getBytes());
+// fos.close();
+// } catch (IOException e) {
+// String errmsg =
+// _localStrings.getLocalString("j2ee.startupslow",
+// "Cannot write the seed file for fast startup. The next startup will be slow.");
+//
+// _logger.log(Level.WARNING, errmsg);
+// }
+//
+// }
+
+ public ServiceLocator getHabitat() {
+ return habitat;
+ }
+
+ public AuditManager getAuditManager() {
+ return auditManager;
+ }
+
+ public static SecurityServicesUtil getInstance() {
+ // return my singleton service
+ if (habitat == null) {
+ return null;
+ }
+ return habitat.getService(SecurityServicesUtil.class);
+ }
+
+ public ProcessEnvironment getProcessEnv() {
+ return processEnv;
+ }
+
+ public boolean isACC() {
+ return processEnv.getProcessType().equals(ProcessType.ACC);
+ }
+ public boolean isServer() {
+ return processEnv.getProcessType().isServer();
+ }
+ public boolean isNotServerOrACC() {
+ return processEnv.getProcessType().equals(ProcessType.Other);
+ }
+
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityUpgradeService.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityUpgradeService.java
new file mode 100644
index 0000000..9f3fd92
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/SecurityUpgradeService.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.config.serverbeans.*;
+import java.beans.PropertyVetoException;
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.api.admin.config.ConfigurationUpgrade;
+import javax.inject.Inject;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+
+
+/**
+ *The only thing that needs to added Extra for SecurityService migration
+ * is the addition of the new JACC provider. This would be required when
+ * migrating from V2, for V3-Prelude it is already present.
+ *
+ * The rest of the security related upgrade is handled implicitly by the actions of the
+ * upgrade service itself.
+ *
+ */
+
+@Service
+public class SecurityUpgradeService implements ConfigurationUpgrade, PostConstruct {
+
+ @Inject
+ Configs configs;
+
+ @Inject
+ ServerEnvironment env;
+
+ private static final String DIR_GENERATED_POLICY = "generated" + File.separator + "policy";
+ private static final String DIR_CONFIG = "config";
+ private static final String JKS = ".jks";
+ private static final String NSS = ".db";
+ // private static final String KEYSTORE = "keystore.jks";
+ // private static final String TRUSTSTORE = "cacerts.jks";
+
+ private static final String JDBC_REALM_CLASSNAME = "com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm";
+ public static final String PARAM_DIGEST_ALGORITHM = "digest-algorithm";
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+
+ public void postConstruct() {
+ for (Config config : configs.getConfig()) {
+ SecurityService service = config.getSecurityService();
+ if (service != null) {
+ upgradeJACCProvider(service);
+ }
+ }
+
+ //Clear up the old policy files for applications
+ String instanceRoot = env.getInstanceRoot().getAbsolutePath();
+ File genPolicyDir = new File(instanceRoot, DIR_GENERATED_POLICY);
+ if(genPolicyDir != null) {
+ File[] applicationDirs = genPolicyDir.listFiles();
+ if(applicationDirs != null) {
+ for(File policyDir:applicationDirs) {
+ deleteFile(policyDir);
+ }
+ }
+ }
+
+ //Update an existing JDBC realm-Change the digest algorithm to MD5 if none exists
+ //Since the default algorithm is SHA-256 in v3.1, but was MD5 prior to 3.1
+
+ for (Config config : configs.getConfig()) {
+ SecurityService service = config.getSecurityService();
+ List<AuthRealm> authRealms = service.getAuthRealm();
+
+ try {
+ for (AuthRealm authRealm : authRealms) {
+ if (JDBC_REALM_CLASSNAME.equals(authRealm.getClassname())) {
+ Property digestAlgoProp = authRealm.getProperty(PARAM_DIGEST_ALGORITHM);
+ if (digestAlgoProp != null) {
+ String digestAlgo = digestAlgoProp.getValue();
+ if (digestAlgo == null || digestAlgo.isEmpty()) {
+ digestAlgoProp.setValue("MD5");
+ }
+ } else {
+ ConfigSupport.apply(new SingleConfigCode<AuthRealm>() {
+ public Object run(AuthRealm updatedAuthRealm) throws PropertyVetoException, TransactionFailure {
+ Property prop1 = updatedAuthRealm.createChild(Property.class);
+ prop1.setName(PARAM_DIGEST_ALGORITHM);
+ prop1.setValue("MD5");
+ updatedAuthRealm.getProperty().add(prop1);
+ return null;
+ }
+ }, authRealm);
+ }
+ }
+ }
+ } catch (PropertyVetoException pve) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.securityUpgradeServiceException, pve);
+ throw new RuntimeException(pve);
+ } catch (TransactionFailure tf) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.securityUpgradeServiceException, tf);
+ throw new RuntimeException(tf);
+
+ }
+ }
+
+ //Detect an NSS upgrade scenario and point to the steps wiki
+
+ if (requiresSecureAdmin()) {
+
+ _logger.log(Level.WARNING, SecurityLoggerInfo.securityUpgradeServiceWarning);
+ }
+
+ }
+
+
+ /*
+ * Method to detect an NSS install.
+ */
+
+ public boolean requiresSecureAdmin() {
+
+ String instanceRoot = env.getInstanceRoot().getAbsolutePath();
+ File configDir = new File(instanceRoot, "config");
+ //default KS password
+
+
+ if (configDir.isDirectory()) {
+ for (File configFile : configDir.listFiles()) {
+ if (configFile.getName().endsWith(NSS)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private void upgradeJACCProvider(SecurityService securityService) {
+ try {
+ List<JaccProvider> jaccProviders = securityService.getJaccProvider();
+ for (JaccProvider jacc : jaccProviders) {
+ if ("com.sun.enterprise.security.jacc.provider.SimplePolicyConfigurationFactory".equals(jacc.getPolicyConfigurationFactoryProvider())) {
+ //simple policy provider already present
+ return;
+ }
+ }
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ @Override
+ public Object run(SecurityService secServ) throws PropertyVetoException, TransactionFailure {
+ JaccProvider jacc = secServ.createChild(JaccProvider.class);
+ //add the simple provider to the domain's security service
+ jacc.setName("simple");
+ jacc.setPolicyConfigurationFactoryProvider("com.sun.enterprise.security.jacc.provider.SimplePolicyConfigurationFactory");
+ jacc.setPolicyProvider("com.sun.enterprise.security.jacc.provider.SimplePolicyProvider");
+ secServ.getJaccProvider().add(jacc);
+ return secServ;
+ }
+ }, securityService);
+ } catch (TransactionFailure ex) {
+ Logger.getAnonymousLogger().log(Level.SEVERE, null, ex);
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+
+ private boolean deleteFile(File path) {
+ if (path != null && path.exists()) {
+ if (path.isDirectory()) {
+ File[] files = path.listFiles();
+ for(File file:files) {
+ if(file.isDirectory()){
+ deleteFile(file);
+ if(file.delete())
+ continue;
+ }
+ else {
+ if(file.delete())
+ continue;
+ }
+ }
+ }
+ if(!path.delete()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/TextLoginDialog.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/TextLoginDialog.java
new file mode 100644
index 0000000..85d3f5e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/TextLoginDialog.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.ssl.SSLUtils;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.logging.*;
+import javax.security.auth.callback.*;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.logging.*;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import org.glassfish.internal.api.Globals;
+
+/**
+ * This implementation of LoginDialog
+ * If these are not set, then it queries the user in the command window.
+ *
+ * @author Harish Prabandham
+ */
+public final class TextLoginDialog implements LoginDialog {
+
+ private static Logger _logger = null;
+
+ static {
+ _logger = SecurityLoggerInfo.getLogger();
+ }
+ private String username = null;
+ private char[] password = null;
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(TextLoginDialog.class);
+
+ public TextLoginDialog(Callback[] callbacks) {
+ try {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ NameCallback nc = (NameCallback) callbacks[i];
+ System.err.print(nc.getPrompt());
+ if (nc.getDefaultName() != null) {
+ System.err.print("[" + nc.getDefaultName() + "]: ");
+ } else {
+ System.err.print(": ");
+ }
+
+ System.err.flush();
+ username = (new BufferedReader(new InputStreamReader(System.in))).readLine();
+ if ((nc.getDefaultName() != null) && ((username == null) || (username.trim().length() == 0))) {
+ username = nc.getDefaultName();
+ }
+ nc.setName(username);
+
+ } else if (callbacks[i] instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callbacks[i];
+ char[] passwd = null;
+ Object consoleObj = null;
+ Method readPasswordMethod = null;
+ try {
+ Method consoleMethod = System.class.getMethod("console");
+ consoleObj = consoleMethod.invoke(null);
+ readPasswordMethod =
+ consoleObj.getClass().getMethod(
+ "readPassword", String.class,
+ Array.newInstance(Object.class, 1).getClass());
+ } catch (Exception ex) {
+ }
+
+ if (consoleObj != null && readPasswordMethod != null) {
+ passwd = (char[]) readPasswordMethod.invoke(
+ consoleObj, "%s",
+ new Object[]{pc.getPrompt()});
+ } else {
+ System.err.print(pc.getPrompt());
+ System.err.flush();
+ passwd = readPassword(System.in);
+ }
+ if (passwd != null) {
+ pc.setPassword(passwd);
+ Arrays.fill(passwd, ' ');
+ }
+ } else if (callbacks[i] instanceof ChoiceCallback) {
+ ChoiceCallback cc = (ChoiceCallback) callbacks[i];
+ /* Get the keystore password to see if the user is
+ * authorized to see the list of certificates
+ */
+ String lbl = (localStrings.getLocalString("enterprise.security.keystore",
+ "Enter the KeyStore Password "));
+ SSLUtils sslUtils = Globals.get(SSLUtils.class);
+ System.out.println(lbl
+ + " : (max 3 tries)");
+ int cnt = 0;
+ for (cnt = 0; cnt < 3; cnt++) {
+ // Let the user try putting password thrice
+ System.out.println(lbl + " : ");
+ String s = (new BufferedReader(new InputStreamReader(System.in))).readLine();
+ if (s != null) {
+ char[] kp = s.toCharArray();
+ if (sslUtils.verifyMasterPassword(kp)) {
+ break;
+ } else {
+ String errmessage = localStrings.getLocalString("enterprise.security.IncorrectKeystorePassword", "Incorrect Keystore Password");
+ System.err.println(errmessage);
+ }
+ Arrays.fill(kp, ' ');
+ }
+ }
+ if (cnt >= 3) {
+ cc.setSelectedIndex(-1);
+ } else {
+ System.err.println(cc.getPrompt());
+ System.err.flush();
+ String[] choices = cc.getChoices();
+ for (int j = 0; j < choices.length; j++) {
+ System.err.print("[" + j + "] ");
+ System.err.println(choices[j]);
+ }
+ String line =
+ (new BufferedReader(new InputStreamReader(System.in))).readLine();
+
+ if (line != null) {
+ int sel = Integer.parseInt(line);
+ cc.setSelectedIndex(sel);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE,
+ SecurityLoggerInfo.usernamePasswordEnteringSecurityError, e);
+ }
+
+ }
+
+ /**
+ * @return The username of the user.
+ */
+ public String getUserName() {
+ return username;
+ }
+
+ /**
+ *@return The password of the user in plain text...
+ */
+ public final char[] getPassword() {
+ return (password == null) ? null : Arrays.copyOf(password, password.length);
+ }
+
+ private static char[] readPassword(InputStream in) throws IOException {
+ char[] lineBuffer;
+ char[] buf;
+ int i;
+
+ buf = lineBuffer = new char[128];
+ int room = buf.length;
+ int offset = 0;
+ int c;
+
+ loop:
+ while (true) {
+ switch (c = in.read()) {
+ case -1:
+ case '\n':
+ break loop;
+
+ case '\r':
+ int c2 = in.read();
+ if ((c2 != '\n') && (c2 != -1)) {
+ if (!(in instanceof PushbackInputStream)) {
+ in = new PushbackInputStream(in);
+ }
+ ((PushbackInputStream) in).unread(c2);
+ } else {
+ break loop;
+
+
+ }
+ default:
+ if (--room < 0) {
+ buf = new char[offset + 128];
+ room = buf.length - offset - 1;
+ System.arraycopy(lineBuffer, 0, buf, 0, offset);
+ Arrays.fill(lineBuffer, ' ');
+ lineBuffer = buf;
+ }
+ buf[offset++] = (char) c;
+ break;
+ }
+ }
+
+ if (offset == 0) {
+ return null;
+ }
+
+ char[] ret = new char[offset];
+ System.arraycopy(buf, 0, ret, 0, offset);
+ Arrays.fill(buf, ' ');
+
+ return ret;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/UsernamePasswordStore.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/UsernamePasswordStore.java
new file mode 100644
index 0000000..4d653f3
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/UsernamePasswordStore.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import com.sun.enterprise.security.common.ClientSecurityContext;
+import java.util.logging.*;
+import com.sun.logging.*;
+import java.util.Arrays;
+
+
+/**
+ * This class is used to share information between either of the following scenarios
+ * 1. Different points of execution of a single thread
+ * 2. Different threads that wish to share the username and password information
+ *
+ * Which of the above two condition is applicable depends upon the system property key
+ * "com.sun.appserv.iiopclient.perthreadauth";
+ * When set to true, scenario #1 above applies and the username/password
+ * information is not shared between threads.
+ * When set to false, scenario #2 above applies and the username/password
+ * information stored by one thread is global and visible to all threads.
+ */
+public final class UsernamePasswordStore {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ private static final boolean isPerThreadAuth =
+ Boolean.getBoolean(ClientSecurityContext.IIOP_CLIENT_PER_THREAD_FLAG);
+
+ private static ThreadLocal localUpc =
+ isPerThreadAuth ? new ThreadLocal() : null;
+ private static UsernamePasswordStore sharedUpc;
+
+ private final String username;
+ private final char[] password;
+
+ /**
+ * This creates a new UsernamePasswordStore object.
+ * The constructor is marked as private.
+ *
+ * @param username
+ * @param password
+ */
+ private UsernamePasswordStore(String username, char[] password) {
+ //Copy the password to another reference before storing it to the
+ //instance field.
+ char[] passwordCopy = (password == null) ? null : Arrays.copyOf(password, password.length);
+ this.password = passwordCopy;
+ this.username = username;
+
+ }
+
+ /**
+ * This method returns a UsernamePasswordStore, that is
+ * either thread-local or global depending on the system property
+ * IIOP_PER_THREAD_CLIENT_FLAG.
+ * This method is marked as private.
+ *
+ * @return The current UsernamePasswordStore
+ */
+ private static UsernamePasswordStore get() {
+ if (isPerThreadAuth) {
+ return (UsernamePasswordStore) localUpc.get();
+ } else {
+ synchronized (UsernamePasswordStore.class) {
+ return sharedUpc;
+ }
+ }
+ }
+
+ /**
+ * This method sets the username and password as thread-local or global variable
+ *
+ * @param username
+ * @param password
+ */
+ public static void set(String username, char[] password) {
+ if (isPerThreadAuth) {
+ localUpc.set(new UsernamePasswordStore(username, password));
+ } else {
+ synchronized (UsernamePasswordStore.class) {
+ sharedUpc = new UsernamePasswordStore(username, password);
+ }
+ }
+ }
+
+ /**
+ * Clears the username and password, that might have been previously stored,
+ * either globally or locally to each thread.
+ */
+ public static void reset() {
+ if (isPerThreadAuth) {
+ localUpc.set(null);
+ } else {
+ synchronized (UsernamePasswordStore.class) {
+ sharedUpc = null;
+ }
+ }
+ }
+
+ /**
+ * Clears the username and password only is they were stored locally
+ * to each thread
+ */
+ public static void resetThreadLocalOnly() {
+ if (isPerThreadAuth) {
+ localUpc.set(null);
+ }
+ }
+
+ /**
+ * Returns the username, that was previously stored.
+ *
+ * @return The username set previously or null if not set
+ */
+ public static String getUsername() {
+ UsernamePasswordStore ups = UsernamePasswordStore.get();
+ if( ups != null )
+ return ups.username;
+ else
+ return null;
+ }
+
+
+ /**
+ * Returns the password, that was previously stored.
+ *
+ * @return The password set previously or null if not set
+ */
+ public static char[] getPassword() {
+ UsernamePasswordStore ups = UsernamePasswordStore.get();
+ if( ups != null ) {
+ //Copy the password to another reference before returning it
+ char[] passwordCopy = (ups.password == null) ? null : Arrays.copyOf(ups.password, ups.password.length);
+ return passwordCopy;
+ }
+ else
+ return null;
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerProbeProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerProbeProvider.java
new file mode 100644
index 0000000..5291125
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerProbeProvider.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.external.probe.provider.annotations.Probe;
+import org.glassfish.external.probe.provider.annotations.ProbeParam;
+import org.glassfish.external.probe.provider.annotations.ProbeProvider;
+
+
+@ProbeProvider(moduleProviderName = "glassfish", moduleName = "security", probeProviderName = "web")
+public class WebSecurityDeployerProbeProvider {
+
+
+ /*@Probe(name = "webDeploymentStartedEvent")
+ public void webDeploymentStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "webDeploymentEndedEvent")
+ public void webDeploymentEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }*/
+
+ @Probe(name = "policyCreationStartedEvent")
+ public void policyCreationStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "policyCreationEndedEvent")
+ public void policyCreationEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+/* @Probe(name = "webUndeploymentStartedEvent")
+ public void webUndeploymentStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "webUndeploymentEndedEvent")
+ public void webUndeploymentEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }*/
+
+ @Probe(name = "policyDestructionStartedEvent")
+ public void policyDestructionStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "policyDestructionEndedEvent")
+ public void policyDestructionEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerCreationEvent")
+ public void securityManagerCreationEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerCreationStartedEvent")
+ public void securityManagerCreationStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerCreationEndedEvent")
+ public void securityManagerCreationEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerDestructionEvent")
+ public void securityManagerDestructionEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerDestructionStartedEvent")
+ public void securityManagerDestructionStartedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "securityManagerDestructionEndedEvent")
+ public void securityManagerDestructionEndedEvent(
+ @ProbeParam("appName") String appName) {
+ }
+
+ @Probe(name = "policyCreationEvent")
+ public void policyCreationEvent(
+ @ProbeParam("contextId") String appName) {
+ }
+
+ @Probe(name = "policyDestructionEvent")
+ public void policyDestructionEvent(
+ @ProbeParam("contextId") String appName) {
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerStatsProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerStatsProvider.java
new file mode 100644
index 0000000..0250d7c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/WebSecurityDeployerStatsProvider.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security;
+
+import org.glassfish.external.statistics.CountStatistic;
+import org.glassfish.external.statistics.impl.CountStatisticImpl;
+import org.glassfish.gmbal.Description;
+import org.glassfish.gmbal.AMXMetadata;
+import org.glassfish.gmbal.ManagedAttribute;
+import org.glassfish.gmbal.ManagedObject;
+import org.glassfish.external.probe.provider.annotations.ProbeListener;
+import org.glassfish.external.probe.provider.annotations.ProbeParam;
+
+/**
+ *
+ * @author nithyasubramanian
+ */
+@AMXMetadata(type="web-security-deployer-mon", group="monitoring", isSingleton=false)
+@ManagedObject
+@Description( "Web application Security Deployment statistics" )
+public class WebSecurityDeployerStatsProvider {
+
+ //Commenting the TimeStatistics to be implemented later
+
+ /* TimeStatisticImpl deploymentTime = new TimeStatisticImpl(0, 0, 0, 0, "DeploymentTime", "milliseconds", "Deployment Time", 0, 0);
+
+ TimeStatisticImpl generationTime = new TimeStatisticImpl(0, 0, 0, 0, "GenerationTime", "milliseconds", "Generation Time", 0, 0);
+
+ TimeStatisticImpl undeploymentTime = new TimeStatisticImpl(0, 0, 0, 0, "UndeploymentTime", "milliseconds", "Undeployment Time", 0, 0);
+
+ TimeStatisticImpl removalTime = new TimeStatisticImpl(0, 0, 0, 0, "RemovalTime", "milliseconds", "Removal Time", 0, 0);*/
+
+ CountStatisticImpl secMgrCount = new CountStatisticImpl("WebSecurityManagerCount", "count", "No of Web security managers");
+
+ CountStatisticImpl policyConfCount= new CountStatisticImpl("WebPolicyConfigurationCount", "count", "No of Policy Configuration Objects");
+
+ /* @ManagedAttribute(id="depolymenttime")
+ public TimeStatistic getDeploymentTime() {
+ return deploymentTime.getStatistic();
+ }
+
+ @ManagedAttribute(id="generationtime")
+ public TimeStatistic getGenerationTime() {
+ return generationTime.getStatistic();
+ }
+
+ @ManagedAttribute(id="undepolymenttime")
+ public TimeStatistic getUndeploymentTime() {
+ return undeploymentTime.getStatistic();
+ }
+
+
+ @ManagedAttribute(id="removaltime")
+ public TimeStatistic getRemovalTime() {
+ return removalTime.getStatistic();
+ }*/
+
+ @ManagedAttribute(id="websecuritymanagercount")
+ public CountStatistic getWebSMCount() {
+ return secMgrCount;
+
+ }
+
+ @ManagedAttribute(id="webpolicyconfigurationcount")
+ public CountStatistic getPCCount() {
+ return policyConfCount;
+ }
+/* @ProbeListener("glassfish:core:web:webDeploymentStartedEvent")
+ public void webDeploymentStartedEvent(@ProbeParam("appName")String appName){
+ deploymentTime.setStartTime(System.currentTimeMillis());
+ }
+
+ @ProbeListener("glassfish:core:web:webDeploymentEndedEvent")
+ public void webDeploymentEndedEvent(@ProbeParam("appName")String appName){
+
+ }*/
+
+ @ProbeListener("glassfish:security:web:securityManagerCreationEvent")
+ public void securityManagerCreationEvent(
+ @ProbeParam("appName") String appName) {
+ secMgrCount.increment();
+ }
+
+ @ProbeListener("glassfish:security:web:securityManagerDestructionEvent")
+ public void securityManagerDestructionEvent(
+ @ProbeParam("appName") String appName) {
+ secMgrCount.decrement();
+ }
+
+ @ProbeListener("glassfish:security:web:policyCreationEvent")
+ public void policyConfigurationCreationEvent(
+ @ProbeParam("contextId") String contextId) {
+ policyConfCount.increment();
+ }
+
+ @ProbeListener("glassfish:security:web:policyDestructionEvent")
+ public void policyConfigurationDestructionEvent(
+ @ProbeParam("contextId") String contextId) {
+ policyConfCount.decrement();
+ }
+
+
+
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/DisableSecureAdminCommand.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/DisableSecureAdminCommand.java
new file mode 100644
index 0000000..073449e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/DisableSecureAdminCommand.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+
+import java.util.Iterator;
+import org.glassfish.api.I18n;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RestEndpoint;
+import org.glassfish.api.admin.RestEndpoints;
+import org.glassfish.api.admin.RuntimeType;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+ * Adjusts the DAS configuration to turn off secure admin, as if by
+ * executing these commands:
+ * <pre>
+ * {@code
+
+asadmin -s set configs.config.server-config.network-config.network-listeners.network-listener.admin-listener.protocol=admin-listener
+
+asadmin -s delete-protocol sec-admin-listener
+asadmin -s delete-protocol admin-http-redirect
+asadmin -s delete-protocol pu-protocol
+}
+ *
+ * @author Tim Quinn
+ */
+@Service(name = "disable-secure-admin")
+@PerLookup
+@I18n("disable.secure.admin.command")
+@ExecuteOn({RuntimeType.DAS,RuntimeType.INSTANCE})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST,
+ path="disable-secure-admin",
+ description="disable-secure-admin")
+})
+@AccessRequired(resource="domain/secure-admin", action="disable")
+public class DisableSecureAdminCommand extends SecureAdminCommand {
+
+ @Override
+ protected String transactionErrorMessageKey() {
+ return SecurityLoggerInfo.disablingSecureAdminError;
+ }
+
+ @Override
+ Iterator<Work<TopLevelContext>> secureAdminSteps() {
+ return reverseStepsIterator(secureAdminSteps);
+ }
+
+ @Override
+ Iterator<Work<ConfigLevelContext>> perConfigSteps() {
+ return reverseStepsIterator(perConfigSteps);
+ }
+
+ /**
+ * Iterator which returns array elements from back to front.
+ * @param <T>
+ * @param steps
+ * @return
+ */
+ private <T extends SecureAdminCommand.Context> Iterator<Work<T>> reverseStepsIterator(Step<T>[] steps) {
+ return new Iterator<Work<T>> () {
+ private Step<T>[] steps;
+ private int nextSlot;
+
+ @Override
+ public boolean hasNext() {
+ return nextSlot >= 0;
+ }
+
+ /**
+ * Returns the disable work associated with the next step we should
+ * process for disabling secure admin.
+ */
+ @Override
+ public Work<T> next() {
+ return steps[nextSlot--].disableWork();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ Iterator<Work<T>> init(Step<T>[] steps) {
+ this.steps = steps;
+ nextSlot = this.steps.length - 1;
+ return this;
+ }
+
+ }.init(steps);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/EnableSecureAdminCommand.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/EnableSecureAdminCommand.java
new file mode 100644
index 0000000..c663af5
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/EnableSecureAdminCommand.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper.SecureAdminCommandException;
+import com.sun.enterprise.config.serverbeans.SecureAdminPrincipal;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RestEndpoint;
+import org.glassfish.api.admin.RestEndpoints;
+import org.glassfish.api.admin.RuntimeType;
+import javax.inject.Inject;
+import org.glassfish.api.admin.AccessRequired;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Records that secure admin is to be used and adjusts each admin listener
+ * configuration in the domain to use secure admin.
+ *
+ * The command changes the admin-listener set-up within each separate
+ * configuration as if by running
+ * these commands:
+ * <pre>
+ * {@code
+ ###
+ ### create new protocol for secure admin
+ ###
+ asadmin create-protocol --securityenabled=true sec-admin-listener
+ asadmin create-http --default-virtual-server=__asadmin sec-admin-listener
+ #asadmin create-network-listener --listenerport 4849 --protocol sec-admin-listener sec-admin-listener
+ asadmin create-ssl --type network-listener --certname s1as --ssl2enabled=false --ssl3enabled=false --clientauthenabled=false sec-admin-listener
+ asadmin set configs.config.server-config.network-config.protocols.protocol.sec-admin-listener.ssl.client-auth=want
+ asadmin set configs.config.server-config.network-config.protocols.protocol.sec-admin-listener.ssl.classname=com.sun.enterprise.security.ssl.GlassfishSSLImpl
+
+
+ ###
+ ### create the port redirect config
+ ###
+ asadmin create-protocol --securityenabled=false admin-http-redirect
+ asadmin create-http-redirect --secure-redirect true admin-http-redirect
+ #asadmin create-http-redirect --secure-redirect true --redirect-port 4849 admin-http-redirect
+ asadmin create-protocol --securityenabled=false pu-protocol
+ asadmin create-protocol-finder --protocol pu-protocol --targetprotocol sec-admin-listener --classname org.glassfish.grizzly.config.portunif.HttpProtocolFinder http-finder
+ asadmin create-protocol-finder --protocol pu-protocol --targetprotocol admin-http-redirect --classname org.glassfish.grizzly.config.portunif.HttpProtocolFinder admin-http-redirect
+
+ ###
+ ### update the admin listener
+ ###
+ asadmin set configs.config.server-config.network-config.network-listeners.network-listener.admin-listener.protocol=pu-protocol
+ * }
+ *
+ *
+ * @author Tim Quinn
+ */
+@Service(name = "enable-secure-admin")
+@PerLookup
+@I18n("enable.secure.admin.command")
+@ExecuteOn({RuntimeType.DAS,RuntimeType.INSTANCE})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST,
+ path="enable-secure-admin",
+ description="enable-secure-admin")
+})
+@AccessRequired(resource="domain/secure-admin", action="enable")
+public class EnableSecureAdminCommand extends SecureAdminCommand {
+
+ @Param(optional = true, defaultValue = SecureAdmin.Duck.DEFAULT_ADMIN_ALIAS)
+ public String adminalias;
+
+ @Param(optional = true, defaultValue = SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS)
+ public String instancealias;
+
+ @Inject
+ private SSLUtils sslUtils;
+
+ @Inject
+ private SecureAdminHelper secureAdminHelper;
+
+ private KeyStore keystore = null;
+
+ @Override
+ public void run() throws TransactionFailure, SecureAdminCommandException {
+ try {
+ ensureNoAdminUsersWithEmptyPassword();
+ } catch (SecureAdminCommandException ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new TransactionFailure((ex.getMessage() != null ? ex.getMessage() : ""));
+ }
+ super.run();
+ }
+
+ private void ensureNoAdminUsersWithEmptyPassword() throws SecureAdminCommandException {
+ boolean isAdminUserWithoutPassword;
+ try {
+ isAdminUserWithoutPassword = secureAdminHelper.isAnyAdminUserWithoutPassword();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ if (isAdminUserWithoutPassword) {
+ throw new SecureAdminCommandException(Strings.get("adminsWithEmptyPW"));
+ }
+
+ }
+
+
+ @Override
+ Iterator<Work<TopLevelContext>> secureAdminSteps() {
+ return stepsIterator(secureAdminSteps);
+ }
+
+ @Override
+ Iterator<Work<ConfigLevelContext>> perConfigSteps() {
+ return stepsIterator(perConfigSteps);
+ }
+
+ /**
+ * Iterator which returns array elements from front to back.
+ * @param <T>
+ * @param steps
+ * @return
+ */
+ private <T extends SecureAdminCommand.Context> Iterator<Work<T>> stepsIterator(Step<T>[] steps) {
+ return new Iterator<Work<T>> () {
+ private Step<T>[] steps;
+ private int nextSlot;
+
+ @Override
+ public boolean hasNext() {
+ return nextSlot < steps.length;
+ }
+
+ @Override
+ public Work<T> next() {
+ return steps[nextSlot++].enableWork();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ Iterator<Work<T>> init(Step<T>[] values) {
+ this.steps = values;
+ nextSlot = 0;
+ return this;
+ }
+
+ }.init(steps);
+ }
+
+ @Override
+ protected boolean updateSecureAdminSettings(
+ final SecureAdmin secureAdmin_w) {
+ /*
+ * Apply the values for the aliases. We do this whether the user
+ * gave explicit values or not, because we need to do some work
+ * even for the default aliases.
+ */
+ try {
+ final List<String> badAliases = new ArrayList<String>();
+ secureAdmin_w.setDasAlias(processAlias(adminalias,
+ SecureAdmin.Duck.DEFAULT_ADMIN_ALIAS,
+ secureAdmin_w, badAliases));
+ secureAdmin_w.setInstanceAlias(processAlias(instancealias,
+ SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS,
+ secureAdmin_w, badAliases));
+
+ ensureSpecialAdminIndicatorIsUnique(secureAdmin_w);
+
+ if (badAliases.size() > 0) {
+ throw new SecureAdminCommandException(
+ Strings.get("enable.secure.admin.badAlias",
+ badAliases.size(), badAliases.toString()));
+ }
+ ensureSpecialAdminIndicatorIsUnique(secureAdmin_w);
+ return true;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private String processAlias(String alias, final String defaultAlias, final SecureAdmin secureAdmin_w,
+ Collection<String> badAliases) throws IOException, KeyStoreException {
+ boolean isAliasOK;
+ /*
+ * Do not validate the default aliases. The user might be using
+ * password-based inter-process authentication in which case the aliases
+ * might not even be present in the keystore and/or truststore.
+ */
+ if (alias.equals(defaultAlias)) {
+ isAliasOK = true;
+ } else {
+ isAliasOK = validateAlias(alias);
+ if ( ! isAliasOK) {
+ badAliases.add(alias);
+ }
+ }
+ if (isAliasOK) {
+ /*
+ * If there is no SecureAdminPrincipal for the DN corresponding
+ * to the specified alias then add one now.
+ */
+ ensureSecureAdminPrincipalForAlias(alias,
+ secureAdmin_w);
+ }
+ return alias;
+ }
+
+ @Override
+ protected String transactionErrorMessageKey() {
+ return SecurityLoggerInfo.enablingSecureAdminError;
+ }
+
+ private void ensureSpecialAdminIndicatorIsUnique(final SecureAdmin secureAdmin_w) {
+ if (secureAdmin_w.getSpecialAdminIndicator().equals(SecureAdmin.Util.ADMIN_INDICATOR_DEFAULT_VALUE)) {
+ /*
+ * Set the special admin indicator to a unique identifier.
+ */
+ final UUID uuid = UUID.randomUUID();
+ secureAdmin_w.setSpecialAdminIndicator(uuid.toString());
+ }
+ }
+
+ /**
+ * Makes sure there is a SecureAdminPrincipal entry for the specified
+ * alias. If not, one is added in the context of the current
+ * transaction.
+ *
+ * @param alias the alias to check for
+ * @param secureAdmin_w SecureAdmin instance (already in a transaction)
+ */
+ private void ensureSecureAdminPrincipalForAlias(final String alias,
+ final SecureAdmin secureAdmin_w) {
+ SecureAdminPrincipal p = getSecureAdminPrincipalForAlias(alias, secureAdmin_w);
+ if (p != null) {
+ return;
+ }
+ try {
+ /*
+ * Create a new SecureAdminPrincipal.
+ */
+ final String dn = secureAdminHelper.getDN(alias, true);
+ p = secureAdmin_w.createChild(SecureAdminPrincipal.class);
+ p.setDn(dn);
+ secureAdmin_w.getSecureAdminPrincipal().add(p);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private SecureAdminPrincipal getSecureAdminPrincipalForAlias(final String alias,
+ final SecureAdmin secureAdmin_w) {
+ try {
+ final String dnForAlias = secureAdminHelper.getDN(alias, true);
+ for (SecureAdminPrincipal p : secureAdmin_w.getSecureAdminPrincipal()) {
+ if (p.getDn().equals(dnForAlias)) {
+ return p;
+ }
+ }
+ return null;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private synchronized KeyStore keyStore() throws IOException {
+ if (keystore == null) {
+ keystore = sslUtils.getKeyStore();
+ }
+ return keystore;
+ }
+
+ private boolean validateAlias(final String alias) throws IOException, KeyStoreException {
+ return keyStore().containsAlias(alias);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminCommand.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminCommand.java
new file mode 100644
index 0000000..c8efef7
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminCommand.java
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.AdminService;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.JmxConnector;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper.SecureAdminCommandException;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+
+import org.glassfish.grizzly.config.dom.FileCache;
+import org.glassfish.grizzly.config.dom.Http;
+import org.glassfish.grizzly.config.dom.HttpRedirect;
+import org.glassfish.grizzly.config.dom.NetworkConfig;
+import org.glassfish.grizzly.config.dom.NetworkListener;
+import org.glassfish.grizzly.config.dom.PortUnification;
+import org.glassfish.grizzly.config.dom.Protocol;
+import org.glassfish.grizzly.config.dom.ProtocolFinder;
+import org.glassfish.grizzly.config.dom.Protocols;
+import org.glassfish.grizzly.config.dom.Ssl;
+import java.beans.PropertyVetoException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import javax.inject.Inject;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.Transaction;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Provides common behavior for the enable and disable secure admin commands.
+ * <p>
+ * This class, and the concrete subclasses EnableSecureAdminCommand and
+ * DisableSecureAdminComment, define what must be done in terms of steps.
+ * Each step has enable work and disable work. This class builds
+ * arrays of steps, one array which operates at the domain level and one which
+ * operates at the config level. The enable work of these steps is run in order through
+ * the array to fully
+ * enable secure admin, and the disable work of these steps are run in REVERSE
+ * order to fully disable secure admin.
+ * <p>
+ * I have defined the steps and their enable and disable work here, together
+ * in some inner classes, rather than separately in the EnableSecureAdminCommand
+ * and DisableSecureAdminCommand classes to try to keep common details together.
+ * The concrete subclasses can override a few methods, in particular overriding
+ * methods which return an Iterator over the steps to be performed. This way we
+ * have a single array of all the steps, with each class returning a forward-running
+ * or reverse-running iterator over those steps.
+ *
+ * @author Tim Quinn
+ */
+public abstract class SecureAdminCommand implements AdminCommand {
+
+ final static String SEC_ADMIN_LISTENER_PROTOCOL_NAME = "sec-admin-listener";
+ private final static String REDIRECT_PROTOCOL_NAME = "admin-http-redirect";
+ public final static String ADMIN_LISTENER_NAME = "admin-listener";
+ static final String DAS_CONFIG_NAME = "server-config";
+ final static String PORT_UNIF_PROTOCOL_NAME = "pu-protocol";
+
+ static final Logger logger = SecurityLoggerInfo.getLogger();
+
+
+ @Inject
+ protected Domain domain;
+
+ /**
+ * Applies changes other than whether secure admin is enabled or disabled
+ * to the secure-admin element.
+ * <p>
+ * This method is primarily for the enable processing to apply the
+ * admin and/or instance alias values, if specified on the enable-secure-admin
+ * command, to the secure-admin element.
+ *
+ * @param secureAdmin_w
+ * @return
+ */
+ boolean updateSecureAdminSettings(
+ final SecureAdmin secureAdmin_w) throws TransactionFailure {
+ /*
+ * Default implementation - currently used by DisableSecureAdminCommand
+ * and overridden by EnableSecureAdminCommand.
+ */
+ return true;
+ }
+
+ interface Context {
+ }
+
+ /**
+ * Work to be performed - either for enable or disable - in a step.
+ * @param <T>
+ */
+ interface Work<T extends Context> {
+ boolean run(final T context) throws TransactionFailure;
+ }
+
+ /**
+ * A step to be performed during enabling or disabling secure admin.
+ *
+ * @param <T> either TopLevelContext or ConfigLevelContext, depending on
+ * whether the step applies per-domain or per-config.
+ */
+ interface Step<T extends Context> {
+ Work<T> enableWork();
+ Work<T> disableWork();
+ }
+
+// interface TopLevelStep {
+// TopLevelWork enableWork();
+// TopLevelWork disableWork();
+// }
+
+// /**
+// * The contract for performing the work associate with a single step of
+// * enabling or disabling secure admin.
+// */
+// interface SecureAdminWork<T> {
+// boolean run(
+// Transaction t,
+// AdminCommandContext context,
+// T writeableConfigBean) throws TransactionFailure;
+// }
+//
+// /**
+// * Enabling or disabling secure admin each involves multiple steps.
+// * Each step has some logic run during enable and some logic run during disable
+// * @param <T>
+// */
+// interface SecureAdminStep<T> {
+// SecureAdminWork<T> enableWork();
+// SecureAdminWork<T> disableWork();
+// }
+
+ static class AbstractContext implements Context {
+ }
+
+ /**
+ * Keeps track of whether we've found writable versions of various
+ * ConfigBeans.
+ */
+ static class TopLevelContext extends AbstractContext {
+
+ private final Transaction t;
+ private final Domain d;
+ private Domain d_w = null;
+
+ private SecureAdmin secureAdmin_w = null;
+
+ TopLevelContext(
+ final Transaction t,
+ final Domain d) {
+ this.t = t;
+ this.d = d;
+ }
+
+
+ Domain writableDomain() throws TransactionFailure {
+ if (d_w == null) {
+ d_w = t.enroll(d);
+ }
+ return d_w;
+ }
+
+ /*
+ * Gets the SecureAdmin object in writeable form, from the specified
+ * domain if the SecureAdmin object already exists or by creating a new
+ * one attached to the domain if one does not already exist.
+ */
+ SecureAdmin writableSecureAdmin() throws TransactionFailure {
+ if (secureAdmin_w == null) {
+
+ /*
+ * Create the secure admin node if it is not already there.
+ */
+ SecureAdmin secureAdmin = d.getSecureAdmin();
+ if (secureAdmin == null) {
+ secureAdmin_w = writableDomain().createChild(SecureAdmin.class);
+ writableDomain().setSecureAdmin(secureAdmin_w);
+ } else {
+ /*
+ * It already existed, so join it to the transaction.
+ */
+ secureAdmin_w = t.enroll(secureAdmin);
+ }
+ }
+ return secureAdmin_w;
+ }
+ }
+
+ /**
+ * Tracks writable config beans for each configuration.
+ */
+ static class ConfigLevelContext extends AbstractContext {
+
+ private static final String CLIENT_AUTH_VALUE = "want";
+ private static final String SSL3_ENABLED_VALUE = "false";
+ private static final String CLASSNAME_VALUE = "com.sun.enterprise.security.ssl.GlassfishSSLImpl";
+
+ private final Transaction t;
+ private final Config config_w;
+ private final TopLevelContext topLevelContext;
+
+ private Protocols protocols_w = null;
+ private Map<String,Protocol> namedProtocols_w = new
+ HashMap<String,Protocol>();
+
+ private JmxConnector jmxConnector_w = null;
+ private Ssl jmxConnectorSsl_w = null;
+
+ ConfigLevelContext(
+ final TopLevelContext topLevelContext,
+ final Config config_w) {
+ this.topLevelContext = topLevelContext;
+ this.t = topLevelContext.t;
+ this.config_w = config_w;
+ }
+
+ /**
+ * Prepares a given Ssl configuration instance so the connection
+ * represented by the Ssl's parent configuration object operates
+ * securely, using SSL.
+ *
+ * @param ssl_w writeable Ssl instance to be modified
+ * @param certNickname the cert nickname to be used by the connection to identify itself
+ * @return
+ */
+ private static Ssl initSsl(final Ssl ssl_w, final String certNickname) {
+ ssl_w.setClientAuth(CLIENT_AUTH_VALUE);
+ ssl_w.setSsl3Enabled(SSL3_ENABLED_VALUE);
+ ssl_w.setClassname(CLASSNAME_VALUE);
+ ssl_w.setCertNickname(certNickname);
+ ssl_w.setRenegotiateOnClientAuthWant(true);
+ return ssl_w;
+ }
+
+ private static String chooseCertNickname(
+ final String configName,
+ final String dasAlias,
+ final String instanceAlias) throws TransactionFailure {
+ return (configName.equals(DAS_CONFIG_NAME) ? dasAlias : instanceAlias);
+ }
+
+ private JmxConnector writeableJmxConnector() throws TransactionFailure {
+ if (jmxConnector_w == null) {
+ final AdminService adminService = config_w.getAdminService();
+ if (adminService == null) {
+ return null;
+ }
+ final JmxConnector jmxC = adminService.getSystemJmxConnector();
+ if (jmxC == null) {
+ return null;
+ }
+ jmxConnector_w = t.enroll(jmxC);
+ }
+ return jmxConnector_w;
+ }
+
+ private Ssl writeableJmxSSL() throws TransactionFailure, PropertyVetoException {
+ if (jmxConnectorSsl_w == null) {
+ final JmxConnector jmxC_w = writeableJmxConnector();
+ if (jmxC_w == null) {
+ return null;
+ }
+ Ssl jmxConnectorSsl = jmxC_w.getSsl();
+ if (jmxConnectorSsl == null) {
+ jmxConnectorSsl = jmxC_w.createChild(Ssl.class);
+ jmxC_w.setSsl(jmxConnectorSsl);
+ jmxConnectorSsl_w = jmxConnectorSsl;
+ } else {
+ jmxConnectorSsl_w = t.enroll(jmxConnectorSsl);
+ }
+ }
+ return jmxConnectorSsl_w;
+ }
+ private Protocols writableProtocols() throws TransactionFailure {
+ if (protocols_w == null) {
+ final NetworkConfig nc = config_w.getNetworkConfig();
+ if (nc == null) {
+ return null;
+ }
+ final Protocols p = nc.getProtocols();
+ protocols_w = t.enroll(p);
+ }
+ return protocols_w;
+ }
+
+ private Protocol writableProtocol(final String protocolName,
+ final boolean isSecure) throws TransactionFailure {
+ Protocol p_w = namedProtocols_w.get(protocolName);
+ if (p_w == null) {
+ /*
+ * Try to find an existing entry for this protocol.
+ */
+ final Protocol p_r = findProtocol(protocolName);
+ if (p_r == null) {
+ final Protocols ps_w = writableProtocols();
+ if (ps_w == null) {
+ return null;
+ }
+ p_w = ps_w.createChild(Protocol.class);
+ p_w.setName(protocolName);
+ ps_w.getProtocol().add(p_w);
+ } else {
+ p_w = t.enroll(p_r);
+ }
+ namedProtocols_w.put(protocolName, p_w);
+ }
+ p_w.setSecurityEnabled(Boolean.toString(isSecure));
+ return p_w;
+ }
+
+ private Protocol findProtocol(final String protocolName) {
+ final NetworkConfig nc = config_w.getNetworkConfig();
+ if (nc == null) {
+ return null;
+ }
+ final Protocols ps = nc.getProtocols();
+ if (ps == null) {
+ return null;
+ }
+ return ps.findProtocol(protocolName);
+ }
+
+ private void deleteProtocol(
+ final String protocolName) throws TransactionFailure {
+ final Protocols ps_w = writableProtocols();
+ if (ps_w == null) {
+ return;
+ }
+ final Protocol doomedProtocol = ps_w.findProtocol(protocolName);
+ if (doomedProtocol != null) {
+ ps_w.getProtocol().remove(doomedProtocol);
+ }
+ }
+ }
+
+ /**
+ * Updates the secure-admin element itself.
+ * <p>
+ * The concrete command implementation classes implement updateSecureAdminSettings
+ * differently but they expose the same method signature, so onEnable and
+ * onDisable just invoke the same method.
+ */
+ private Step<TopLevelContext> perDomainStep = new Step<TopLevelContext>() {
+
+ /**
+ * Sets enabled=true/false on the secure-admin element.
+ */
+ private void updateSecureAdminEnabledSetting(
+ final SecureAdmin secureAdmin_w,
+ final boolean newEnabledValue) {
+ secureAdmin_w.setEnabled(Boolean.toString(newEnabledValue));
+ }
+
+ /*
+ * Both the enable and disable steps for the "secure admin element only"
+ * task set the enabled value and then let the concrete command
+ * subclass do any additional work.
+ */
+ class TopLevelWork implements Work<TopLevelContext> {
+
+ private final boolean newEnabledState;
+
+ TopLevelWork(final boolean newEnabledState) {
+ this.newEnabledState = newEnabledState;
+ }
+
+ @Override
+ public boolean run(final TopLevelContext context) throws TransactionFailure {
+ final SecureAdmin secureAdmin_w = context.writableSecureAdmin();
+ updateSecureAdminEnabledSetting(
+ secureAdmin_w, newEnabledState);
+ /*
+ * The subclass might have overridden updateSecureAdminSettings.
+ * Give it a change to run logic specific to enable or disable.
+ */
+ return SecureAdminCommand.this.updateSecureAdminSettings(secureAdmin_w);
+ }
+ }
+
+ @Override
+ public Work<TopLevelContext> enableWork() {
+ return new TopLevelWork(true);
+ };
+
+ @Override
+ public Work<TopLevelContext> disableWork() {
+ return new TopLevelWork(false);
+ }
+ };
+
+ /**
+ * Manages the jmx-connector settings.
+ */
+ private Step<ConfigLevelContext> jmxConnectorStep = new Step<ConfigLevelContext>() {
+
+ /**
+ * Sets the jmx-connector security-enabled to true and creates and
+ * initializes the child ssl element.
+ */
+ @Override
+ public Work<ConfigLevelContext> enableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(ConfigLevelContext context) throws TransactionFailure {
+ /*
+ * Make sure the JMX connector is enabled for secure operation.
+ * Then make sure the JMX Connector's SSL child is present
+ * and correctly set up.
+ */
+ final JmxConnector jmxConnector_w = context.writeableJmxConnector();
+ if (jmxConnector_w == null) {
+ return false;
+ }
+ try {
+ jmxConnector_w.setSecurityEnabled("true");
+ final Ssl ssl_w = context.writeableJmxSSL();
+ ConfigLevelContext.initSsl(ssl_w, ConfigLevelContext.chooseCertNickname(
+ context.config_w.getName(),
+ context.topLevelContext.writableSecureAdmin().dasAlias(),
+ context.topLevelContext.writableSecureAdmin().instanceAlias()));
+ return true;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public Work<ConfigLevelContext> disableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(ConfigLevelContext context) throws TransactionFailure {
+ /*
+ * Remove the SSL child of the JMX configuration. Then
+ * turn off the security-enabled attribute of the JMX config.
+ */
+ final JmxConnector jmxC_w = context.writeableJmxConnector();
+ try {
+ jmxC_w.setSsl(null);
+ jmxC_w.setSecurityEnabled("false");
+ return true;
+ } catch (PropertyVetoException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ };
+ }
+ };
+
+ /**
+ * Manages the sec-admin-listener protocol.
+ */
+ private Step<ConfigLevelContext> secAdminListenerProtocolStep = new Step<ConfigLevelContext>() {
+
+ private static final String ASADMIN_VIRTUAL_SERVER_NAME = "__asadmin";
+
+ private static final String AUTH_LAYER_NAME = "HttpServlet";
+ private static final String PROVIDER_ID_VALUE = "GFConsoleAuthModule";
+
+ private Http writeableHttpWithFileCacheChild(final Transaction t,
+ final Protocol secAdminListenerProtocol_w) throws TransactionFailure {
+ /*
+ * Because of the calling context, the secAdminListenerProtocol is already
+ * writeable -- it was just created moments ago and has not yet
+ * been committed.
+ */
+ Http http_w;
+ Http http = secAdminListenerProtocol_w.getHttp();
+ if (http == null) {
+ http_w = secAdminListenerProtocol_w.createChild(Http.class);
+ secAdminListenerProtocol_w.setHttp(http_w);
+ } else {
+ http_w = t.enroll(http);
+ }
+ http_w.setDefaultVirtualServer(ASADMIN_VIRTUAL_SERVER_NAME);
+ http_w.setEncodedSlashEnabled("true");
+
+ final FileCache cache = http_w.createChild(FileCache.class);
+// cache.setEnabled("false");
+ http_w.setFileCache(cache);
+
+ return http_w;
+ }
+
+ private Ssl writeableSsl(final Transaction t,
+ final Protocol secAdminListenerProtocol_w,
+ final String certNickname) throws TransactionFailure {
+ Ssl ssl_w = null;
+ Ssl ssl = secAdminListenerProtocol_w.getSsl();
+ if (ssl == null) {
+ ssl_w = secAdminListenerProtocol_w.createChild(Ssl.class);
+ secAdminListenerProtocol_w.setSsl(ssl_w);
+ } else {
+ ssl_w = t.enroll(ssl);
+ }
+ return ConfigLevelContext.initSsl(ssl_w, certNickname);
+ }
+
+ @Override
+ public Work<ConfigLevelContext> enableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(final ConfigLevelContext context) throws TransactionFailure {
+ /*
+ * Get an existing or new writeable sec-admin-listener protocol.
+ */
+ final Protocol secAdminListenerProtocol_w =
+ context.writableProtocol(SEC_ADMIN_LISTENER_PROTOCOL_NAME,
+ true);
+
+ /*
+ * It seems possible to create configs without network listeners
+ * and children. In that case it's not a real config so we
+ * will skip it.
+ */
+ if (secAdminListenerProtocol_w == null) {
+ return false;
+ }
+
+ /*
+ * Get an existing or create a new writeable http child under the new protocol.
+ */
+ writeableHttpWithFileCacheChild(context.t, secAdminListenerProtocol_w);
+
+ /*
+ * Get an existing or create a new writeable ssl child under the new protocol.
+ * Which cert nickname we set depends on whether this is the DAS's config
+ * we're working on or an instance's.
+ */
+ writeableSsl(context.t, secAdminListenerProtocol_w,
+ ConfigLevelContext.chooseCertNickname(
+ context.config_w.getName(),
+ context.topLevelContext.writableSecureAdmin().dasAlias(),
+ context.topLevelContext.writableSecureAdmin().instanceAlias()));
+
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public Work<ConfigLevelContext> disableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(ConfigLevelContext context) throws TransactionFailure {
+
+
+ context.deleteProtocol(SEC_ADMIN_LISTENER_PROTOCOL_NAME);
+
+ return true;
+ }
+ };
+ }
+ };
+
+ private enum ProtocolFinderInfo {
+ HTTP_FINDER("http-finder", SEC_ADMIN_LISTENER_PROTOCOL_NAME),
+ ADMIN_HTTP_REDIRECT_FINDER("admin-http-redirect", REDIRECT_PROTOCOL_NAME);
+
+ private final String name;
+ private final String protocolName;
+ private final String classname = "org.glassfish.grizzly.config.portunif.HttpProtocolFinder";
+
+ private ProtocolFinderInfo(final String name, final String protocolName) {
+ this.name = name;
+ this.protocolName = protocolName;
+ }
+
+ }
+
+ private Step<ConfigLevelContext> secAdminPortUnifAndRedirectStep = new Step<ConfigLevelContext>() {
+
+ private final static String PORT_UNIF_PROTOCOL_NAME = "pu-protocol";
+ private final static String UNSECURE_ADMIN_LISTENER_PROTOCOL_NAME = "admin-listener";
+
+ private final static String HTTP_FINDER_PROTOCOL_FINDER_NAME = "http-finder";
+ private final static String ADMIN_HTTP_REDIRECT_FINDER_NAME = "admin-http-redirect";
+
+ private final static String PROTOCOL_FINDER_CLASSNAME = "org.glassfish.grizzly.config.portunif.HttpProtocolFinder";
+
+
+ private HttpRedirect writeableHttpRedirect(
+ final Transaction t,
+ final Protocol adminHttpRedirectProtocol_w) throws TransactionFailure {
+ HttpRedirect redirect = adminHttpRedirectProtocol_w.getHttpRedirect();
+ HttpRedirect redirect_w;
+ if (redirect == null) {
+ redirect_w = adminHttpRedirectProtocol_w.createChild(HttpRedirect.class);
+ adminHttpRedirectProtocol_w.setHttpRedirect(redirect_w);
+ } else {
+ redirect_w = t.enroll(redirect);
+ }
+ redirect_w.setSecure(Boolean.TRUE.toString());
+ return redirect_w;
+ }
+
+ private PortUnification writeablePortUnification(
+ final Transaction t,
+ final Protocol protocol_w) throws TransactionFailure {
+ PortUnification pu_w;
+ PortUnification pu = protocol_w.getPortUnification();
+ if (pu == null) {
+ pu_w = protocol_w.createChild(PortUnification.class);
+ protocol_w.setPortUnification(pu_w);
+ } else {
+ pu_w = t.enroll(pu);
+ }
+ return pu_w;
+ }
+
+ private ProtocolFinder writeableProtocolFinder(
+ final Transaction t,
+ final PortUnification pu_w,
+ final ProtocolFinderInfo finderInfo) throws TransactionFailure {
+ ProtocolFinder pf_w = null;
+ for (ProtocolFinder pf : pu_w.getProtocolFinder()) {
+ if (pf.getName().equals(finderInfo.name)) {
+ pf_w = t.enroll(pf);
+ break;
+ }
+ }
+ if (pf_w == null) {
+ pf_w = pu_w.createChild(ProtocolFinder.class);
+ pu_w.getProtocolFinder().add(pf_w);
+ }
+ pf_w.setName(finderInfo.name);
+ pf_w.setClassname(finderInfo.classname);
+ pf_w.setProtocol(finderInfo.protocolName);
+ return pf_w;
+ }
+
+ private NetworkListener writableNetworkListener(
+ final Transaction t,
+ final Config config_w,
+ final String listenerName) throws TransactionFailure {
+ NetworkListener nl_w = null;
+ final NetworkConfig nc = config_w.getNetworkConfig();
+ if (nc == null) {
+ return null;
+ }
+ NetworkListener nl = nc.getNetworkListener(listenerName);
+ if (nl == null) {
+ return null;
+ } else {
+ nl_w = t.enroll(nl);
+ }
+ return nl_w;
+ }
+
+
+
+ private void assignAdminListenerProtocol(
+ final Transaction t,
+ final Config config_w,
+ final String protocolName) throws TransactionFailure {
+ final NetworkListener nl_w = writableNetworkListener(t, config_w, ADMIN_LISTENER_NAME);
+ if (nl_w != null) {
+ nl_w.setProtocol(protocolName);
+ }
+ }
+
+ @Override
+ public Work<ConfigLevelContext> enableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(ConfigLevelContext context) throws TransactionFailure {
+ /*
+ * Get an existing or new writeable admin-http-redirect protocol.
+ */
+
+ final Protocol adminHttpRedirectProtocol_w =
+ context.writableProtocol(
+ REDIRECT_PROTOCOL_NAME,
+ false);
+
+ if (adminHttpRedirectProtocol_w == null) {
+ return true;
+ }
+
+ writeableHttpRedirect(
+ context.t, adminHttpRedirectProtocol_w);
+
+ final Protocol puProtocol_w = context.writableProtocol(
+ PORT_UNIF_PROTOCOL_NAME,
+ false);
+
+ final PortUnification portUnif_w = writeablePortUnification(
+ context.t, puProtocol_w);
+
+ writeableProtocolFinder(
+ context.t, portUnif_w, ProtocolFinderInfo.HTTP_FINDER);
+
+ writeableProtocolFinder(
+ context.t, portUnif_w, ProtocolFinderInfo.ADMIN_HTTP_REDIRECT_FINDER);
+
+ assignAdminListenerProtocol(context.t, context.config_w, PORT_UNIF_PROTOCOL_NAME);
+
+ return true;
+ }
+ };
+ }
+
+ @Override
+ public Work<ConfigLevelContext> disableWork() {
+ return new Work<ConfigLevelContext>() {
+
+ @Override
+ public boolean run(final ConfigLevelContext context) throws TransactionFailure {
+ final Config config_w = context.config_w;
+ final Transaction t = context.t;
+ assignAdminListenerProtocol(t, config_w, UNSECURE_ADMIN_LISTENER_PROTOCOL_NAME);
+
+ context.deleteProtocol(PORT_UNIF_PROTOCOL_NAME);
+ context.deleteProtocol(REDIRECT_PROTOCOL_NAME);
+ return true;
+ }
+
+ };
+ }
+
+ };
+
+// /**
+// * Details for managing the protocol associated directly with the
+// * admin listener. This logic takes care of creating
+// * the sec-admin-listener protocol and assoociating it with
+// * the admin listener, or deleting the sec-admin-listener protocol and
+// * associating the admin listener back with the original protocol.
+// */
+// private SecureAdminWork adminListenerProtocolSetting = new SecureAdminWork<Config>() {
+//
+// private final static String ADMIN_LISTENER_NETWORK_LISTENER_NAME = "admin-listener";
+// private final static String ORIGINAL_ADMIN_LISTENER_PROTOCOL_NAME = "admin-listener";
+//
+//
+// @Override
+// public boolean onEnable(
+// final Transaction t,
+// final AdminCommandContext context,
+// final Config tConfig) throws TransactionFailure {
+// writeableAdminNetworkListener(tConfig).
+// setProtocol(SEC_ADMIN_LISTENER_PROTOCOL_NAME);
+// return true;
+// }
+//
+// @Override
+// public boolean onDisable(
+// final Transaction t,
+// final AdminCommandContext context,
+// final Config tConfig
+// ) throws TransactionFailure {
+// writeableAdminNetworkListener(tConfig).
+// setProtocol(ORIGINAL_ADMIN_LISTENER_PROTOCOL_NAME);
+// return true;
+// }
+//
+// private NetworkListener writeableAdminNetworkListener(
+// final Config tConfig) throws TransactionFailure {
+// return tConfig.getNetworkConfig().
+// getNetworkListener(ADMIN_LISTENER_NETWORK_LISTENER_NAME);
+// }
+
+// private NetworkListener writeableAdminNetworkListener(
+// final Transaction t,
+// final Config tConfig) throws TransactionFailure {
+// ConfigSupport.apply(new SingleConfigCode<NetworkListener>() {
+// @Override
+// public Object run(NetworkListener nl) throws PropertyVetoException, TransactionFailure {
+//
+// try {
+//
+// for (Config c : configs.getConfig()) {
+// final MessagePart partForThisConfig = report.getTopMessagePart().addChild();
+//
+// /*
+// * Again, delegate to update the admin
+// * listener configuration.
+// */
+// updateAdminListenerConfig(context, t, c, partForThisConfig);
+// }
+//
+// t.commit();
+// } catch (RetryableException ex) {
+// throw new RuntimeException(ex);
+// }
+//
+// return Boolean.TRUE;
+// }
+// }, tConfig.getNetworkConfig().getNetworkListener(ADMIN_LISTENER_NETWORK_LISTENER_NAME));
+// }
+//
+// };
+
+ /**
+ * Tasks executed once per enable or disable.
+ */
+ final Step<TopLevelContext>[] secureAdminSteps =
+ new Step[] {
+ perDomainStep
+ };
+
+
+ /**
+ * Tasks executed once per config during an enable or disable.
+ */
+ final Step<ConfigLevelContext>[] perConfigSteps =
+ new Step[] {
+ secAdminListenerProtocolStep,
+ secAdminPortUnifAndRedirectStep,
+ jmxConnectorStep
+ };
+
+ /**
+ * Returns the error key for finding a message describing an error
+ * during the operation - either enable or disable.
+ * <p>
+ * Each concrete subclass overrides this to supply the relevant message key.
+ *
+ * @return the message key corresponding to the error message to display
+ */
+ protected abstract String transactionErrorMessageKey();
+
+ /**
+ * Returns an Iterator over the work (enable work for enable-secure-admin,
+ * disable for disable-secure-admin) for the steps related to
+ * just the top-level secure-admin element.
+ *
+ * @return
+ */
+ abstract Iterator<Work<TopLevelContext>> secureAdminSteps();
+
+ /**
+ * Returna an Iterator over the work related to each configuration that
+ * has to be modified.
+ *
+ * @return
+ */
+ abstract Iterator<Work<ConfigLevelContext>> perConfigSteps();
+
+ /**
+ * Performs the enable/disable logic for secure admin.
+ * <p>
+ * This is separate from the execute method so it can be invoked during
+ * upgrade.
+ *
+ * @throws TransactionFailure
+ */
+ public void run() throws TransactionFailure, SecureAdminCommandException {
+ ConfigSupport.apply(new SingleConfigCode<Domain>() {
+ @Override
+ public Object run(Domain domain_w) throws PropertyVetoException, TransactionFailure {
+
+ // get the transaction
+ final Transaction t = Transaction.getTransaction(domain_w);
+ final TopLevelContext topLevelContext =
+ new TopLevelContext(t, domain_w);
+ if (t!=null) {
+
+ /*
+ * Do the work on just the secure-admin element.
+ */
+ for (Iterator<Work<TopLevelContext>> it = secureAdminSteps(); it.hasNext();) {
+ final Work<TopLevelContext> step = it.next();
+ if ( ! step.run(topLevelContext) ) {
+ t.rollback();
+ return Boolean.FALSE;
+ }
+ }
+
+ /*
+ * Now apply the required changes to the admin listener
+ * in the configurations. Include all configs, because even
+ * though the non-DAS configs default to use SSL the user
+ * might have specified a different alias to use and that
+ * value must be set in the SSL element for the
+ * secure admin listener.
+ */
+ final Configs configs = domain_w.getConfigs();
+ for (Config c : configs.getConfig()) {
+ final Config c_w = t.enroll(c);
+ ConfigLevelContext configLevelContext =
+ new ConfigLevelContext(topLevelContext, c_w);
+ for (Iterator<Work<ConfigLevelContext>> it = perConfigSteps(); it.hasNext();) {
+ final Work<ConfigLevelContext> step = it.next();
+ if ( ! step.run(configLevelContext)) {
+ t.rollback();
+ return Boolean.FALSE;
+ }
+ }
+ }
+ }
+
+ return Boolean.TRUE;
+ }
+ }, domain);
+ }
+ /**
+ * Executes the particular xxx-secure-admin command (enable or disable).
+ * @param context
+ */
+ @Override
+ public void execute(final AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ try {
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ run();
+ report.setMessage(Strings.get("restartReq"));
+ } catch (TransactionFailure ex) {
+ report.failure(context.getLogger(), Strings.get(transactionErrorMessageKey()), ex);
+ } catch (SecureAdminCommandException ex) {
+ report.failure(context.getLogger(), ex.getLocalizedMessage());
+ }
+ }
+
+ /*
+ * Executes the command with no action report. Primarily useful from the
+ * upgrade class (which does not have a convenient action report).
+ */
+ void execute() throws TransactionFailure, SecureAdminCommandException {
+ try {
+ run();
+ } catch (TransactionFailure ex) {
+ logger.log(Level.SEVERE, Strings.get(transactionErrorMessageKey()), ex);
+ throw ex;
+ } catch (SecureAdminCommandException ex) {
+ logger.log(Level.SEVERE, ex.getLocalizedMessage());
+ throw ex;
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigMonitor.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigMonitor.java
new file mode 100644
index 0000000..0766b3e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigMonitor.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import java.beans.PropertyChangeEvent;
+import java.util.logging.Logger;
+
+import org.glassfish.hk2.runlevel.RunLevel;
+import org.glassfish.internal.api.PostStartupRunLevel;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.Changed;
+import org.jvnet.hk2.config.Changed.TYPE;
+import org.jvnet.hk2.config.ConfigBeanProxy;
+import org.jvnet.hk2.config.ConfigListener;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.NotProcessed;
+import org.jvnet.hk2.config.UnprocessedChangeEvents;
+
+/**
+ * Tracks changes to secure admin configuration, basically so it can report
+ * restart-required.
+ *
+ * @author Tim Quinn
+ */
+@Service
+@RunLevel(PostStartupRunLevel.VAL)
+public class SecureAdminConfigMonitor implements ConfigListener {
+
+ private static final String restartRequiredMsg = Strings.get("secure.admin.change.requires.restart");
+
+ /*
+ * Must inject Domain to get notifications of SecureAdmin changes. We
+ * cannot inject SecureAdmin itself because it might be null and that
+ * bothers some components.
+ */
+ @Inject
+ private Domain domain;
+
+ private Logger logger = SecurityLoggerInfo.getLogger();
+
+
+ @Override
+ public UnprocessedChangeEvents changed(final PropertyChangeEvent[] events) {
+ return ConfigSupport.sortAndDispatch(
+ events, new Changed() {
+ @Override
+ public <T extends ConfigBeanProxy> NotProcessed changed(TYPE type,
+ Class<T> tClass, T t) {
+ if (t instanceof Domain) {
+ return processDomain(type, (Domain) t, events);
+ } else if (t instanceof SecureAdmin) {
+ return processSecureAdmin(type, (SecureAdmin) t, events);
+ }
+ return null;
+ }
+ }, logger);
+ }
+
+ private NotProcessed processDomain(final TYPE type, final Domain d,
+ final PropertyChangeEvent[] events) {
+ for (PropertyChangeEvent event : events) {
+ if ( (event.getOldValue() instanceof SecureAdmin && type == Changed.TYPE.REMOVE)
+ || (event.getNewValue() instanceof SecureAdmin && type == Changed.TYPE.ADD) ) {
+ return new NotProcessed(restartRequiredMsg);
+ }
+ }
+ return null;
+ }
+
+ private NotProcessed processSecureAdmin(final TYPE type, final SecureAdmin sa,
+ final PropertyChangeEvent[] events) {
+ /*
+ * Any change to the secure admin config requires a restart.
+ */
+ return new NotProcessed(restartRequiredMsg);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigUpgrade.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigUpgrade.java
new file mode 100644
index 0000000..bea48d7
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminConfigUpgrade.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.HttpService;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper.SecureAdminCommandException;
+import com.sun.enterprise.config.serverbeans.VirtualServer;
+import com.sun.enterprise.security.SecurityUpgradeService;
+import com.sun.enterprise.universal.process.ProcessManager;
+import com.sun.enterprise.universal.process.ProcessManagerException;
+import com.sun.enterprise.util.net.NetUtils;
+import org.glassfish.grizzly.config.dom.NetworkConfig;
+import org.glassfish.grizzly.config.dom.NetworkListener;
+import org.glassfish.grizzly.config.dom.NetworkListeners;
+import org.glassfish.grizzly.config.dom.Protocol;
+import org.glassfish.grizzly.config.dom.Ssl;
+import java.beans.PropertyVetoException;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.UnknownHostException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.api.admin.config.ConfigurationUpgrade;
+import org.glassfish.config.support.GrizzlyConfigSchemaMigrator;
+import javax.inject.Inject;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.internal.api.Globals;
+import org.glassfish.security.common.MasterPassword;
+import org.jvnet.hk2.config.RetryableException;
+import org.jvnet.hk2.config.Transaction;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Upgrades older config to current.
+ *
+ * In 3.1.2 GlassFish uses SSL for DAS-to-instance traffic regardless of
+ * whether the user enables secure admin. This means that the upgrade must
+ * always:
+ * <ol>
+ * <li>Create the secure-admin element.
+ * <li>Add the glassfish-instance private key to the keystore and the
+ * corresponding self-signed cert to the truststore.
+ * <li>Add secure-admin-principal children to secure-admin, one for alias s1as and
+ * one for glassfish-instance.
+ * <li>Add the Grizzly config for the non-DAS admin listener configurations to use port unification
+ * and redirection (and SSL).
+ * <li>If it seems the user has configured the old domain to use secure admin
+ * traffic then run the enable-secure-admin command.
+ * </ol>
+ *
+ * @author Tim Quinn
+ */
+@Service
+public class SecureAdminConfigUpgrade extends SecureAdminUpgradeHelper implements ConfigurationUpgrade, PostConstruct {
+
+ public SecureAdminConfigUpgrade() {
+
+ }
+ private final static String ADMIN_LISTENER_NAME = "admin-listener";
+
+ /*
+ * Constants used for creating a missing network-listener during upgrade.
+ * Ideally this will be handled in the grizzly upgrade code.
+ */
+ private final static String ASADMIN_LISTENER_PORT = "${ASADMIN_LISTENER_PORT}";
+ private final static String ASADMIN_LISTENER_TRANSPORT = "tcp";
+ private final static String ASADMIN_LISTENER_THREADPOOL = "http-thread-pool";
+
+ private final static String ASADMIN_VS_NAME = "__asadmin";
+
+ private static final Logger logger = Logger.getAnonymousLogger();
+
+ // Thanks to Jerome for suggesting this injection to make sure the
+ // Grizzly migration runs before this migration
+ @Inject
+ private GrizzlyConfigSchemaMigrator grizzlyMigrator;
+
+ @Inject
+ private SecurityUpgradeService securityUpgradeService;
+
+ @Inject
+ private Configs configs;
+
+ @Inject
+ private ServerEnvironment serverEnv;
+
+ /**
+ * Inject this to make sure it is initialized. It is used by
+ * SecuritySupportImpl, but because SecuritySupportImpl is not a service
+ * hk2 does not operate on it and would not automatically initialize
+ * MasterPassword.
+ */
+ @Inject
+ private MasterPassword masterPassword;
+
+ private Map<String,Config> writableConfigs = new HashMap<String,Config>();
+
+ @Override
+ public void postConstruct() {
+ /*
+ * Make sure the darn Globals is set up, because it's used downstream
+ * from SecuritySupportImpl.
+ */
+ if (Globals.getDefaultHabitat() == null) {
+ Globals.setDefaultHabitat(habitat);
+ }
+ String stage = null;
+ try {
+ stage = "adding admin-listener to non-DAS configuration";
+ ensureNonDASConfigsHaveAdminNetworkListener();
+ logger.log(Level.INFO, "Added admin-listener network listeners to non-DAS configurations");
+
+ stage = "upgrading config for secure DAS-to-instance admin traffic";
+ setupNewDefaultConfig();
+
+ /*
+ * See if we need to set up secure admin during the upgrade.
+ */
+ if (requiresSecureAdmin()) {
+ final EnableSecureAdminCommand enableSecureAdminCommand =
+ habitat.getService(EnableSecureAdminCommand.class);
+ stage = "upgrading secure admin set-up";
+ try {
+ enableSecureAdminCommand.run();
+ logger.log(Level.INFO, "Upgraded secure admin set-up");
+ } catch (SecureAdminCommandException ex) {
+ logger.log(Level.INFO,
+ "Attempt to upgrade secure admin set-up failed",
+ ex);
+ throw ex;
+ }
+ } else {
+ logger.log(Level.INFO, "No secure admin set-up was detected in the original configuration so no upgrade of it was needed");
+ }
+ commit();
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Error " + stage, ex);
+ rollback();
+ }
+ }
+
+ private void setupNewDefaultConfig() throws
+ IOException, NoSuchAlgorithmException, CertificateException,
+ KeyStoreException, UnrecoverableKeyException, ProcessManagerException, TransactionFailure, RetryableException, PropertyVetoException {
+ /*
+ * In 3.1.2 the default config has a secure-admin element with child secure-admin-principal
+ * elements for the s1as and glassfish-instance aliases. The keystore
+ * contains private keys for s1as and glassfish-instance (new in 3.x)
+ * and the truststore contains the self-signed certs for those two
+ * aliases.
+ */
+ ensureKeyPairForInstanceAlias();
+
+ /*
+ * Add the secure-admin-principal children below secure-admin, one for
+ * the DAS alias and one for the instance alias.
+ */
+ ensureSecureAdminReady();
+ prepareDASConfig();
+// prepareNonDASConfigs();
+ }
+
+ private boolean requiresSecureAdmin() {
+ return isOriginalAdminSecured() || securityUpgradeService.requiresSecureAdmin();
+ }
+
+ private void prepareDASConfig() throws TransactionFailure, PropertyVetoException {
+ final Config dasConfig = writableConfig(configs.getConfigByName(DAS_CONFIG_NAME));
+ final NetworkConfig nc = dasConfig.getNetworkConfig();
+ final NetworkListener nl_w = transaction().enroll(nc.getNetworkListener(SecureAdminCommand.ADMIN_LISTENER_NAME));
+ nl_w.setProtocol(SecureAdminCommand.ADMIN_LISTENER_NAME);
+ }
+
+// private void prepareNonDASConfigs() throws TransactionFailure, PropertyVetoException {
+// for (Config c : configs.getConfig()) {
+// if (c.getName().equals(DAS_CONFIG_NAME)) {
+// continue;
+// }
+// ensureConfigReady(c, SecureAdminCommand.PORT_UNIF_PROTOCOL_NAME);
+// }
+// }
+
+ private void ensureConfigReady(final Config c, final String adminListenerProtocol) throws TransactionFailure, PropertyVetoException {
+ final NetworkConfig nc = c.getNetworkConfig();
+ final NetworkListener nl = nc.getNetworkListener(SecureAdminCommand.ADMIN_LISTENER_NAME);
+ if (nl != null) {
+ return;
+ }
+
+ /*
+ * Create an admin-listener for this configuration.
+ */
+ final Config config_w = writableConfig(c);
+
+ createAdminNetworkListener(transaction(), nc, adminListenerProtocol);
+ createAdminVirtualServer(transaction(), config_w);
+ }
+
+ private Config writableConfig(final Config c) throws TransactionFailure {
+ Config result = writableConfigs.get(c.getName());
+ if (result == null) {
+ result = transaction().enroll(c);
+ writableConfigs.put(c.getName(), result);
+ }
+ return result;
+ }
+
+ private void ensureNonDASConfigsHaveAdminNetworkListener() throws TransactionFailure, PropertyVetoException {
+
+ for (Config c : configs.getConfig()) {
+ if (c.getName().equals(DAS_CONFIG_NAME)) {
+ continue;
+ }
+ ensureConfigReady(c, SecureAdminCommand.PORT_UNIF_PROTOCOL_NAME);
+ }
+ }
+
+
+
+ private NetworkListener createAdminNetworkListener(
+ final Transaction t,
+ final NetworkConfig nc,
+ final String adminListenerProtocolName) throws TransactionFailure {
+ final NetworkListeners nls_w = t.enroll(nc.getNetworkListeners());
+ final NetworkListener nl_w = nls_w.createChild(NetworkListener.class);
+ nls_w.getNetworkListener().add(nl_w);
+ nl_w.setName(ADMIN_LISTENER_NAME);
+ nl_w.setProtocol(adminListenerProtocolName);
+ nl_w.setPort(ASADMIN_LISTENER_PORT);
+ nl_w.setTransport(ASADMIN_LISTENER_TRANSPORT);
+ nl_w.setThreadPool(ASADMIN_LISTENER_THREADPOOL);
+ return nl_w;
+ }
+
+ private VirtualServer createAdminVirtualServer(
+ final Transaction t,
+ final Config config_w) throws TransactionFailure, PropertyVetoException {
+ final HttpService hs_w = t.enroll(config_w.getHttpService());
+ final VirtualServer vs_w = hs_w.createChild(VirtualServer.class);
+ hs_w.getVirtualServer().add(vs_w);
+ vs_w.setId(ASADMIN_VS_NAME);
+ vs_w.setNetworkListeners(ADMIN_LISTENER_NAME);
+ return vs_w;
+ }
+
+
+
+ private boolean isOriginalAdminSecured() {
+ /*
+ * The Grizzly conversion has already occurred. So look for
+ *
+ * <server-config>
+ * <network-config>
+ * <protocols>
+ * <protocol name="admin-listener">
+ * <ssl ...>
+ *
+ */
+ final Config serverConfig;
+ final NetworkConfig nc;
+ final Protocol p;
+ final Ssl ssl ;
+ if ((serverConfig = configs.getConfigByName(SecureAdminUpgradeHelper.DAS_CONFIG_NAME)) == null) {
+ return false;
+ }
+
+ if ((nc = serverConfig.getNetworkConfig()) == null) {
+ return false;
+ }
+
+ if ((p = nc.findProtocol(ADMIN_LISTENER_NAME)) == null) {
+ return false;
+ }
+
+
+ if ((ssl = p.getSsl()) == null) {
+ return false;
+ }
+ return true;
+ }
+
+ private void ensureKeyPairForInstanceAlias() throws IOException, NoSuchAlgorithmException, CertificateException, KeyStoreException, UnrecoverableKeyException, ProcessManagerException {
+ /*
+ * No need to add glassfish-instance to the keystore if it already exists.
+ */
+ final KeyStore ks = sslUtils().getKeyStore();
+ if (ks.containsAlias(SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS)) {
+ return;
+ }
+
+ /*
+ * This is ugly but effective. We need to add a new private key to
+ * the keystore and a new self-signed cert to the truststore. To do so
+ * we run keytool commands to change the on-disk stores, then we
+ * cause the in-memory copies to reload.
+ */
+ final File keyStoreFile = serverEnv.getJKS();
+ final File trustStoreFile = new File(serverEnv.getConfigDirPath(), "cacerts.jks");
+ final String pw = masterPassword();
+
+ ProcessManager pm = new ProcessManager(new String[]{
+ "keytool",
+ "-genkey",
+ "-keyalg", "RSA",
+ "-keystore", keyStoreFile.getAbsolutePath(),
+ "-alias", SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS,
+ "-dname", getCertificateDN(),
+ "-validity", "3650",
+ "-keypass", pw,
+ "-storepass", pw,});
+ pm.execute();
+ if (pm.getExitValue() != 0) {
+ final String err = pm.getStdout();
+ throw new RuntimeException(err);
+ }
+
+ final File tempCertFile = new File(serverEnv.getConfigDirPath(),"temp.cer");
+ tempCertFile.deleteOnExit();
+ pm = new ProcessManager(new String[] {
+ "keytool",
+ "-exportcert",
+ "-keystore", keyStoreFile.getAbsolutePath(),
+ "-alias", SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS,
+ "-keypass", pw,
+ "-storepass", pw,
+ "-file", tempCertFile.getAbsolutePath()
+ });
+ pm.execute();
+
+ if (pm.getExitValue() != 0) {
+ throw new RuntimeException(pm.getStderr());
+ }
+
+ pm = new ProcessManager(new String[] {
+ "keytool",
+ "-importcert",
+ "-noprompt",
+ "-trustcacerts",
+ "-storepass", pw,
+ "-keypass", pw,
+ "-keystore", trustStoreFile.getAbsolutePath(),
+ "-file", tempCertFile.getAbsolutePath(),
+ "-alias", SecureAdmin.Duck.DEFAULT_INSTANCE_ALIAS
+ });
+ pm.execute();
+ if ( ! tempCertFile.delete()) {
+ logger.log(Level.FINE, "Unable to delete temp file {0}; continuing", tempCertFile.getAbsolutePath());
+ }
+
+ if (pm.getExitValue() != 0) {
+ throw new RuntimeException(pm.getStderr());
+ }
+
+ /*
+ * Reload the keystore and truststore from disk.
+ */
+ reload(sslUtils().getKeyStore(), keyStoreFile, pw);
+ reload(sslUtils().getTrustStore(), serverEnv.getTrustStore(), pw);
+ }
+
+ private void reload(final KeyStore keystore, final File keystoreFile, final String pw) throws
+ FileNotFoundException, IOException, NoSuchAlgorithmException, CertificateException {
+
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(keystoreFile));
+ keystore.load(is, pw.toCharArray());
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+
+ private String masterPassword() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
+// /*
+// * Crude way to get the master password of the keystore.
+// */
+// if (masterPassword == null) {
+// masterPassword = habitat.getService(MasterPassword.class);
+// }
+// return masterPassword.getMasterPasswordAdapter().getPasswordForAlias("s1as");
+ String masterPW = "changeit";
+ final String pwFileArg = startupArg("-passwordfile");
+ if (pwFileArg != null) {
+ final String masterPWFromPWFile = pwProps(pwFileArg).getProperty("AS_ADMIN_MASTERPASSWORD");
+ if (masterPWFromPWFile != null) {
+ masterPW = masterPWFromPWFile;
+ }
+ }
+ return masterPW;
+ }
+
+ private Properties pwProps(final String pwFilePath) throws IOException {
+ Properties result = new Properties();
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(pwFilePath));
+ result.load(is);
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ return result;
+ }
+ }
+
+ private static String CERTIFICATE_DN_PREFIX = "CN=";
+
+ private static String CERTIFICATE_DN_SUFFIX =
+ ",OU=GlassFish,O=Oracle Corporation,L=Santa Clara,ST=California,C=US";
+
+ private static final String INSTANCE_CN_SUFFIX = "-instance";
+
+ private String getCertificateDN() throws UnknownHostException {
+ String cn;
+ try {
+ cn = NetUtils.getCanonicalHostName();
+ } catch(Exception e) {
+ cn = "localhost";
+ }
+ /*
+ * Use the suffix, if provided, in creating the DN (by augmenting
+ * the CN).
+ */
+ String x509DistinguishedName = CERTIFICATE_DN_PREFIX + cn +
+ INSTANCE_CN_SUFFIX + CERTIFICATE_DN_SUFFIX;
+ return x509DistinguishedName; //must be of form "CN=..., OU=..."
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminHelperImpl.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminHelperImpl.java
new file mode 100644
index 0000000..637f619
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminHelperImpl.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.AdminService;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.file.FileRealmUser;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import org.glassfish.api.admin.ServerEnvironment;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+ * Various utility methods which support secure admin operations.
+ *
+ * @author Tim Quinn
+ */
+@Service
+@PerLookup
+public class SecureAdminHelperImpl implements SecureAdminHelper {
+
+ private static final char[] emptyPassword = new char[0];
+ private final static String DOMAIN_ADMIN_GROUP_NAME = "asadmin";
+
+
+ @Inject
+ private SSLUtils sslUtils;
+
+ @Inject
+ private DomainScopedPasswordAliasStore domainPasswordAliasStore;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private volatile AdminService as;
+
+ /**
+ * Returns the correct DN to use for a given secure admin principal, mapping
+ * the alias (if it's an alias specified) to the DN for the corresponding
+ * cert in the key store.
+ *
+ * @param value user-provided value (alias name or the actual DN)
+ * @param isAlias whether the value is an alias
+ * @return DN to use
+ * @throws IOException if there is an error accessing the key store
+ * @throws KeyStoreException if the keystore has not been initialized
+ * @throws IllegalArgumentException if the cert for the specified alias as fetched from the key store is not an X509 certificate
+ */
+ @Override
+ public String getDN(final String value, final boolean isAlias) throws IOException, KeyStoreException {
+ if (isAlias) {
+ final KeyStore keyStore = sslUtils.getKeyStore();
+ if (keyStore == null) {
+ throw new RuntimeException(Strings.get("noKeyStore"));
+ }
+ final Certificate cert = keyStore.getCertificate(value);
+ if (cert == null) {
+ throw new IllegalArgumentException(Strings.get("noAlias", value));
+ }
+ if ( ! (cert instanceof X509Certificate)) {
+ throw new IllegalArgumentException(Strings.get("certNotX509Certificate", value));
+ }
+ return (((X509Certificate) cert).getSubjectX500Principal().getName());
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Makes sure the username is a valid admin username and that the password
+ * alias is defined. This method does NOT make sure that the password
+ * associated with the username and the password associated with the
+ * password alias are the same.
+ *
+ * @param username user-provided username
+ * @param passwordAlias name of the password alias
+ */
+ @Override
+ public void validateInternalUsernameAndPasswordAlias(String username, String passwordAlias) {
+ try {
+ validateUser(username);
+ validatePasswordAlias(passwordAlias);
+ } catch (Exception ex) {
+ throw new RuntimeException(Strings.get("errVal"), ex);
+ }
+ }
+
+ private void validateUser(final String username) throws BadRealmException, NoSuchRealmException {
+ final FileRealm fr = adminRealm();
+ try {
+ FileRealmUser fru = (FileRealmUser)fr.getUser(username);
+ if (isInAdminGroup(fru)) {
+ return;
+ }
+ /*
+ * The user is valid but is not in the admin group.
+ */
+ throw new RuntimeException(Strings.get("notAdminUser", username));
+ } catch (NoSuchUserException ex) {
+ /*
+ * The user is not valid, but use the same error as if the user
+ * IS present but is not an admin user. This provides a would-be
+ * intruder a little less information by not distinguishing
+ * between a valid user that's not an admin user and an
+ * invalid user.
+ */
+ throw new RuntimeException(Strings.get("notAdminUser", username));
+ }
+ }
+
+ private boolean isInAdminGroup(final FileRealmUser user) {
+ for (String group : user.getGroups()) {
+ if (group.equals(DOMAIN_ADMIN_GROUP_NAME)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void validatePasswordAlias(final String passwordAlias)
+ throws CertificateException, NoSuchAlgorithmException,
+ KeyStoreException, NoSuchAlgorithmException, IOException {
+
+ if ( ! domainPasswordAliasStore.containsKey(passwordAlias)) {
+ throw new RuntimeException(Strings.get("noAlias", passwordAlias));
+ }
+ }
+ private FileRealm adminRealm() throws BadRealmException, NoSuchRealmException {
+ final AuthRealm ar = as.getAssociatedAuthRealm();
+ if (FileRealm.class.getName().equals(ar.getClassname())) {
+ String adminKeyFilePath = ar.getPropertyValue("file");
+ FileRealm fr = new FileRealm(adminKeyFilePath);
+ return fr;
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether at least one admin user has an empty password.
+ *
+ * @return true if at least one admin user has an empty password; false otherwise
+ * @throws BadRealmException
+ * @throws NoSuchRealmException
+ * @throws NoSuchUserException
+ */
+ @Override
+ public boolean isAnyAdminUserWithoutPassword() throws Exception {
+ final FileRealm adminRealm = adminRealm();
+ /*
+ * If the user has configured the admin realm to use a realm other than
+ * the default file realm bypass the check that makes sure no admin users have
+ * an empty password.
+ */
+ if (adminRealm == null) {
+ return false;
+ }
+ for (final Enumeration<String> e = adminRealm.getUserNames(); e.hasMoreElements(); ) {
+ final String username = e.nextElement();
+ /*
+ * Try to authenticate this user with an empty password. If it
+ * works we can stop.
+ */
+ final String[] groupNames = adminRealm.authenticate(username, emptyPassword);
+ if (groupNames != null) {
+ for (String groupName : groupNames) {
+ if (DOMAIN_ADMIN_GROUP_NAME.equals(groupName)) {
+ return true;
+ }
+ }
+ }
+
+ }
+ return false;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminStartupCheck.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminStartupCheck.java
new file mode 100644
index 0000000..f733f2c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminStartupCheck.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import org.glassfish.api.StartupRunLevel;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.runlevel.RunLevel;
+import org.jvnet.hk2.annotations.Service;
+/**
+ *
+ * Starting in GlassFish 3.1.2, the DAS uses SSL to send admin requests to
+ * instances regardless of whether the user has enabled secure admin. For this to
+ * work correctly when upgrading from earlier 3.x releases, there are some changes
+ * to the configuration that must be in place. This start-up service makes
+ * sure that the config is correct as quickly as possible to avoid degrading
+ * start-up performance. (Upgrades from 2.x are handled by the SecureAdminConfigUpgrade
+ * upgrade service.)
+ * <p>
+ * For 3.1.2 and later the configuration needs to include:
+ * <pre>
+ * {@code
+ * <secure-admin special-admin-indicator="xxx">
+ * at least one <secure-admin-principal> element; if none, supply these defaults:
+ *
+ * <secure-admin-principal dn="dn-for-DAS"/>
+ * <secure-admin-principal dn="dn-for-instances"/>
+ * }
+ * </pre>
+ *
+ * Further, the sec-admin-listener set-up needs to be added (if not already there)
+ * for the non-DAS configurations. Note that the work to configure the
+ * listeners and related protocols are already implemented by SecureAdminCommand,
+ * so this class delegates much of its work to that logic.
+ *
+ * @author Tim Quinn
+ */
+@Service
+@RunLevel(StartupRunLevel.VAL)
+public class SecureAdminStartupCheck extends SecureAdminUpgradeHelper implements PostConstruct {
+
+ @Override
+ public void postConstruct() {
+ try {
+ /*
+ * If a formal upgrade is in progress then this Startup service
+ * will be invoked first. The upgrade should take care of things,
+ * so this becomes a no-op.
+ */
+ if (isFormalUpgrade()) {
+ return;
+ }
+ ensureSecureAdminReady();
+ ensureNonDASConfigsReady();
+ commit();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private boolean isFormalUpgrade() {
+ return Boolean.valueOf(startupArg("-upgrade"));
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminUpgradeHelper.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminUpgradeHelper.java
new file mode 100644
index 0000000..cddd9b5
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/SecureAdminUpgradeHelper.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.config.serverbeans.SecureAdminHelper;
+import com.sun.enterprise.config.serverbeans.SecureAdminPrincipal;
+import com.sun.enterprise.module.bootstrap.StartupContext;
+import com.sun.enterprise.security.admin.cli.SecureAdminCommand.ConfigLevelContext;
+import com.sun.enterprise.security.admin.cli.SecureAdminCommand.TopLevelContext;
+import com.sun.enterprise.security.admin.cli.SecureAdminCommand.Work;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.UUID;
+import org.glassfish.grizzly.config.dom.NetworkConfig;
+import org.glassfish.grizzly.config.dom.Protocol;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.jvnet.hk2.config.RetryableException;
+import org.jvnet.hk2.config.Transaction;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Common logic for formal upgrade (i.e., start-domain --upgrade) and
+ * silent upgrade (starting a newer version of GlassFish using an older version's
+ * domain.xml).
+ *
+ * @author Tim Quinn
+ */
+@Service
+@PerLookup
+public class SecureAdminUpgradeHelper {
+
+ protected final static String DAS_CONFIG_NAME = "server-config";
+
+ @Inject
+ protected Domain domain;
+
+ @Inject
+ protected ServiceLocator habitat;
+
+ @Inject
+ protected StartupContext startupContext;
+
+ private Transaction t = null;
+
+ private SecureAdmin secureAdmin = null;
+
+ private TopLevelContext topLevelContext = null;
+ private SecureAdminHelper secureAdminHelper = null;
+ private SSLUtils sslUtils = null;
+
+ private Properties startupArgs = null;
+
+
+ final protected Transaction transaction() {
+ if (t == null) {
+ t = new Transaction();
+ }
+ return t;
+ }
+
+ private TopLevelContext topLevelContext() {
+ if (topLevelContext == null) {
+ topLevelContext = new TopLevelContext(transaction(), domain);
+ }
+ return topLevelContext;
+ }
+
+ final protected void commit() throws RetryableException, TransactionFailure {
+ if (t != null) {
+ t.commit();
+ }
+ }
+
+ final protected void rollback() {
+ if (t != null) {
+ t.rollback();
+ }
+ }
+
+ final protected String specialAdminIndicator() {
+ final UUID uuid = UUID.randomUUID();
+ return uuid.toString();
+ }
+
+ final protected SecureAdmin secureAdmin() throws TransactionFailure {
+ if (secureAdmin == null) {
+ secureAdmin = domain.getSecureAdmin();
+ if (secureAdmin == null) {
+ secureAdmin = /* topLevelContext(). */writableSecureAdmin();
+ secureAdmin.setSpecialAdminIndicator(specialAdminIndicator());
+ }
+ }
+ return secureAdmin;
+ }
+
+ final protected Domain writableDomain() throws TransactionFailure {
+ return topLevelContext().writableDomain();
+ }
+
+ final protected SecureAdmin writableSecureAdmin() throws TransactionFailure {
+ return topLevelContext().writableSecureAdmin();
+ }
+
+ final protected SecureAdminHelper secureAdminHelper() {
+ if (secureAdminHelper == null) {
+ secureAdminHelper = habitat.getService(SecureAdminHelper.class);
+ }
+ return secureAdminHelper;
+ }
+
+ final protected SSLUtils sslUtils() {
+ if (sslUtils == null) {
+ sslUtils = habitat.getService(SSLUtils.class);
+ }
+ return sslUtils;
+ }
+
+ final protected void ensureSecureAdminReady() throws TransactionFailure, IOException, KeyStoreException {
+ if (secureAdmin().getSpecialAdminIndicator().isEmpty()) {
+ /*
+ * Set the indicator to a unique value so we can distinguish
+ * one domain from another.
+ */
+ writableSecureAdmin().setSpecialAdminIndicator(specialAdminIndicator());
+ }
+ if (secureAdmin().getSecureAdminPrincipal().isEmpty() &&
+ secureAdmin().getSecureAdminInternalUser().isEmpty()) {
+ /*
+ * Add principal(s) for the aliases.
+ */
+ addPrincipalForAlias(secureAdmin().dasAlias());
+ addPrincipalForAlias(secureAdmin().instanceAlias());
+ }
+ }
+
+ final protected String startupArg(final String argName) {
+ if (startupArgs == null) {
+ if (startupContext != null) {
+ startupArgs = startupContext.getArguments();
+ } else {
+ startupArgs = new Properties(); // shouldn't happen
+ }
+ }
+ return startupArgs.getProperty(argName);
+ }
+
+ private void addPrincipalForAlias(final String alias) throws IOException, KeyStoreException, TransactionFailure {
+ final SecureAdminPrincipal p = writableSecureAdmin().createChild(SecureAdminPrincipal.class);
+ p.setDn(secureAdminHelper().getDN(alias, true));
+ writableSecureAdmin().getSecureAdminPrincipal().add(p);
+ }
+
+ final protected void ensureNonDASConfigsReady() throws TransactionFailure {
+ for (Config c : domain.getConfigs().getConfig()) {
+ if ( ! c.getName().equals(SecureAdminCommand.DAS_CONFIG_NAME)) {
+ if (!ensureConfigReady(c)) {
+ break;
+ }
+ }
+ }
+ }
+
+ final protected void ensureDASConfigReady() {
+
+ }
+
+ private boolean ensureConfigReady(final Config c) throws TransactionFailure {
+ /*
+ * See if this config is already set up for secure admin.
+ */
+ final NetworkConfig nc = c.getNetworkConfig();
+ if (nc == null) {
+ /*
+ * If there is no network config for this configuration then it is
+ * probably a test configuration of some sort. In any case, there
+ * is no lower-level network protocols to verify so declare this
+ * config to be OK.
+ */
+ return true;
+ }
+ Protocol secAdminProtocol = nc.getProtocols().findProtocol(SecureAdminCommand.SEC_ADMIN_LISTENER_PROTOCOL_NAME);
+ if (secAdminProtocol != null) {
+ return true;
+ }
+ final EnableSecureAdminCommand enableCmd = new EnableSecureAdminCommand();
+ final Config c_w = transaction().enroll(c);
+ ConfigLevelContext configLevelContext =
+ new ConfigLevelContext(topLevelContext(), c_w);
+ for (Iterator<Work<ConfigLevelContext>> it = enableCmd.perConfigSteps(); it.hasNext();) {
+ final Work<ConfigLevelContext> step = it.next();
+ if ( ! step.run(configLevelContext)) {
+ rollback();
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/Strings.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/Strings.java
new file mode 100644
index 0000000..9e5ef63
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/admin/cli/Strings.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.admin.cli;
+
+import com.sun.enterprise.universal.i18n.LocalStringsImpl;
+
+/**
+ * Strings -- Get your Strings here.
+ * One file with Strings
+ * So one class for messing with them!
+ * Nothing in here is public protected. Only for use by this one java package.
+ * @author Byron Nevins
+ */
+
+final class Strings {
+ private Strings() {
+ // no instances allowed!
+ }
+
+ final static String get(String indexString) {
+ return strings.get(indexString);
+ }
+
+ final static String get(String indexString, Object... objects) {
+ return strings.get(indexString, objects);
+ }
+
+ final private static LocalStringsImpl strings = new LocalStringsImpl(Strings.class);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/AuditManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/AuditManager.java
new file mode 100644
index 0000000..fd42100
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/AuditManager.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.audit;
+
+import org.jvnet.hk2.annotations.Contract;
+
+
+/**
+ * Defines the behavior for audit manager implementations.
+ *
+ * @author tjquinn
+ */
+@Contract
+public interface AuditManager {
+ /**
+ * Loads all audit modules.
+ */
+ public void loadAuditModules();
+
+ /**
+ * Reports authentication events to registered audit modules.
+ *
+ * @param user
+ * @param realm
+ * @param success
+ */
+ public void authentication(String user, String realm, boolean success);
+
+ /**
+ * Reports server start-up event to registered audit modules.
+ */
+ public void serverStarted();
+
+ /**
+ * Reports server shutdown event to registered audit modules.
+ */
+ public void serverShutdown();
+
+ /**
+ * Returns whether auditing is turned on.
+ *
+ * @return
+ */
+ public boolean isAuditOn();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/BaseAuditManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/BaseAuditManager.java
new file mode 100644
index 0000000..4beac3d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/BaseAuditManager.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/*
+ * BaseAuditManager.java
+ *
+ * Created on July 28, 2003, 1:56 PM
+ */
+
+package com.sun.enterprise.security.audit;
+
+import com.sun.enterprise.security.BaseAuditModule;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.config.serverbeans.AuditModule;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+/*V3:Commented
+import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
+import com.sun.enterprise.config.serverbeans.ElementProperty;
+import com.sun.enterprise.config.ConfigContext;
+import com.sun.enterprise.server.ApplicationServer;
+ */
+import org.glassfish.internal.api.ServerContext;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import java.util.List;
+import org.glassfish.api.admin.ServerEnvironment;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+
+/**
+ * Basic implementation of audit manager.
+ * <p>
+ * Projects layered on top of nucleus should extend this class, adding platform-specific
+ * methods for auditing platform-specific events. See AppServerAuditManagerImpl
+ * for an example. Such implementations should be sure to invoke this class's
+ * setTypeClass method. Then this class will keep a list of AuditModules of
+ * that specific type in the typedModules field which subclasses can refer
+ * to directly.
+ * <p>
+ * (This implementation was largely refactored from the original
+ * BaseAuditManager implementation that combined nucleus and app server features.)
+ *
+ * @author Harpreet Singh
+ * @author Shing Wai Chan
+ * @author tjquinn
+ */
+@Service
+@Singleton
+public class BaseAuditManager<T extends BaseAuditModule> implements AuditManager {
+ static final String NAME = "name";
+ static final String CLASSNAME = "classname";
+
+ // For speed, maintain a separate list of audit modules of the specified
+ // module subtype (if any). This allows subclasses to have very efficient
+ // access to the specified audit modules which the subclass audit manager
+ // deals with.
+ protected List<T> typedModules = Collections.synchronizedList(new ArrayList<T>());
+ private Class<T> typedModuleClass = null; // typically set by postConstruct of a subclass invoking setTypeClass
+
+ private static final Logger _logger =
+ SecurityLoggerInfo.getLogger();
+
+ private static final LocalStringManagerImpl _localStrings =
+ new LocalStringManagerImpl(BaseAuditManager.class);
+
+ private List<BaseAuditModule> instances = Collections.synchronizedList(new ArrayList<BaseAuditModule>());
+ // just a copy of names of the audit classes - helpful for log messages
+ // since we will not have a lot of audit classes, keeping a duplicate copy
+ // seems reasonable.
+ private Map<BaseAuditModule,String> moduleToNameMap = new HashMap<BaseAuditModule,String>();
+ private Map<String,BaseAuditModule> nameToModuleMap = new HashMap<String,BaseAuditModule>();
+ // make this accessible to the containers so that the cost of non-audit case,
+ // is just a comparision.
+ protected boolean auditOn = false;
+
+ @Inject
+ private ServerContext serverContext;
+
+ private static final String AUDIT_MGR_SERVER_STARTUP_KEY =
+ "auditmgr.serverStartup";
+ private static final String AUDIT_MGR_SERVER_SHUTDOWN_KEY =
+ "auditmgr.serverShutdown";
+
+ /**
+ * This method initializes BaseAuditManager which load audit modules and
+ * audit enabled flag
+ */
+ @Override
+ public void loadAuditModules() {
+ try {
+ SecurityService securityBean = serverContext.getDefaultServices().getService(SecurityService.class,
+ ServerEnvironment.DEFAULT_INSTANCE_NAME);
+
+ assert(securityBean != null);
+ // @todo will be removed to incorporate the new structure.
+ //v3:Commented boolean auditFlag = securityBean.isAuditEnabled();
+ boolean auditFlag = Boolean.parseBoolean(securityBean.getAuditEnabled());
+
+ setAuditOn(auditFlag);
+ /*V3:Commented
+ com.sun.enterprise.config.serverbeans.AuditModule[] am =
+ securityBean.getAuditModule();*/
+ List<com.sun.enterprise.config.serverbeans.AuditModule> am = securityBean.getAuditModule();
+ for (com.sun.enterprise.config.serverbeans.AuditModule it: am) {
+ //V3:Commented for (int i = 0; i < am.length; i++){
+ try {
+ //V3:Commented String name = am[i].getName();
+ //V3:Commented String classname = am[i].getClassname();
+ String name = it.getName();
+ String classname = it.getClassname();
+ Properties p = new Properties();
+ //XXX should we remove this two extra properties
+ p.setProperty(NAME, name);
+ p.setProperty(CLASSNAME, classname);
+ List<Property> ep = it.getProperty();
+ /*V3:Commented
+ ElementProperty[] ep = am[i].getElementProperty();
+ int epsize = am[i].sizeElementProperty();
+ for (int j = 0; j < epsize; j++){
+ String nme = ep[j].getName();
+ String val = ep[j].getValue();
+ p.setProperty(nme, val);
+ }*/
+ for (Property prop: ep) {
+ p.setProperty(prop.getName(), prop.getValue());
+ }
+ BaseAuditModule auditModule = loadAuditModule(classname, p);
+ instances.add(auditModule);
+ moduleToNameMap.put(auditModule, name);
+ nameToModuleMap.put(name, auditModule);
+ if (isAuditModuleOfParameterizedType(auditModule)) {
+ typedModules.add((T)auditModule);
+ }
+ } catch(Exception ex){
+ String msg = _localStrings.getLocalString(
+ "auditmgr.loaderror",
+ "Audit: Cannot load AuditModule = {0}",
+ //V3:Commented new Object[]{ am[i].getName() });
+ new Object[]{ it.getName() });
+ _logger.log(Level.WARNING, msg, ex);
+ }
+ }
+ } catch (Exception e) {
+ String msg = _localStrings.getLocalString("auditmgr.badinit",
+ "Audit: Cannot load Audit Module Initialization information. AuditModules will not be loaded.");
+ _logger.log(Level.WARNING, msg, e);
+ }
+ }
+
+ /**
+ * Add the given audit module to the list of loaded audit module.
+ * Adding the same name twice will override previous one.
+ * @param name of auditModule
+ * @param am an instance of a class extending BaseAuditModule that has been
+ * successfully loaded into the system.
+ * @exception
+ */
+ public BaseAuditModule addAuditModule(String name, String classname, Properties props)
+ throws Exception {
+ // make sure only a name corresponding to only one auditModule
+ removeAuditModule(name);
+ BaseAuditModule am = loadAuditModule(classname, props);
+
+ moduleToNameMap.put(am, name);
+ nameToModuleMap.put(name, am);
+ // clone list to resolve multi-thread issues in looping instances
+ instances = copyAndAdd(instances, am);
+ if (isAuditModuleOfParameterizedType(am)) {
+ typedModules = copyAndAdd(typedModules, (T)am);
+ }
+ return am;
+ }
+
+ private boolean isAuditModuleOfParameterizedType(final BaseAuditModule am) {
+ return (typedModuleClass != null && typedModuleClass.isAssignableFrom(am.getClass()));
+ }
+
+ private <U extends BaseAuditModule> List<U> copyAndAdd(final List<U> orig, final U am) {
+ final List<U> list = new ArrayList<U>();
+ Collections.copy(orig, list);
+ list.add(am);
+ return list;
+ }
+
+ private <U extends BaseAuditModule> List<U> copyAndRemove(final List<U> orig, final U am) {
+ final List<U> list = new ArrayList<U>();
+ Collections.copy(orig, list);
+ list.remove(am);
+ return list;
+ }
+
+ /**
+ * Remove the audit module of given name from the loaded list.
+ * @param name of auditModule
+ */
+ public BaseAuditModule removeAuditModule(String name) {
+ final BaseAuditModule am = nameToModuleMap.get(name);
+ if (am != null) {
+ nameToModuleMap.remove(name);
+ moduleToNameMap.remove(am);
+ // clone list to resolve multi-thread issues in looping instances
+ instances = copyAndRemove(instances, am);
+ if (isAuditModuleOfParameterizedType(am)) {
+ typedModules = copyAndRemove(typedModules, (T)am);
+ }
+ }
+ return am;
+ }
+
+ /**
+ * Get the audit module of given name from the loaded list.
+ * @param name of auditModule
+ */
+ BaseAuditModule getAuditModule(String name) {
+ return nameToModuleMap.get(name);
+ }
+
+ /**
+ * This method return auditModule with given classname and properties.
+ * @param classname
+ * @param props
+ * @exception
+ */
+ private BaseAuditModule loadAuditModule(String classname,
+ Properties props) throws Exception {
+ BaseAuditModule auditModule;
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class am = Class.forName(classname, true, loader);
+ Object obj = am.newInstance();
+ auditModule = (BaseAuditModule) obj;
+ auditModule.init(props);
+ return auditModule;
+ }
+
+ public LocalStringManagerImpl getLocalStrings() {
+ return _localStrings;
+ }
+
+ public Logger getLogger() {
+ return _logger;
+ }
+
+ /**
+ * logs the authentication call for all the loaded modules.
+ * @see com.sun.appserv.security.BaseAuditModule.authentication
+ */
+ public void authentication(final String user, final String realm, final boolean success){
+ if (auditOn) {
+ for (BaseAuditModule am : instances) {
+ try {
+ am.authentication(user, realm, success);
+ } catch (Exception ex) {
+ final String name = moduleName(am);
+ final String msg =
+ _localStrings.getLocalString(
+ "auditmgr.authentication",
+ " Audit Module {0} threw the following exception during authentication:",
+ name);
+ _logger.log(Level.INFO, msg, ex);
+ }
+ }
+ }
+ }
+
+ public void serverStarted(){
+ if (auditOn) {
+ for (BaseAuditModule am : instances) {
+ try {
+ am.serverStarted();
+ } catch (Exception ex) {
+ final String name = moduleName(am);
+ final String msg =
+ _localStrings.getLocalString(
+ AUDIT_MGR_SERVER_STARTUP_KEY,
+ " Audit Module {0} threw the following exception during server startup :",
+ name);
+ _logger.log(Level.INFO, msg, ex);
+ }
+ }
+ }
+ }
+
+ public void serverShutdown(){
+ if (auditOn) {
+ for (BaseAuditModule am : instances) {
+ try {
+ am.serverShutdown();
+ } catch (Exception ex) {
+ final String name = moduleName(am);
+ final String msg =
+ _localStrings.getLocalString(
+ AUDIT_MGR_SERVER_SHUTDOWN_KEY,
+ " Audit Module {0} threw the following exception during server shutdown :",
+ name);
+ _logger.log(Level.INFO, msg, ex);
+ }
+ }
+ }
+ }
+
+ public void setAuditOn(boolean auditOn) {
+ this.auditOn = auditOn;
+ }
+
+ public boolean isAuditOn() {
+ return auditOn;
+ }
+
+ protected String moduleName(final BaseAuditModule am) {
+ return moduleToNameMap.get(am);
+ }
+
+ protected List<T> instances(final Class<T> c) {
+ final List<T> result = new ArrayList<T>();
+ for (BaseAuditModule am : instances) {
+ if (c.isAssignableFrom(c)) {
+ result.add((T) am);
+ }
+ }
+ return result;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/LocalStrings.properties
new file mode 100644
index 0000000..2fc941b
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/audit/LocalStrings.properties
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+auditmgr.admininvocation=Audit: Audit Module {0} threw the following exception during admin invocation :
+auditmgr.authentication=Audit: Audit Module {0} threw the following exception during authentication:
+auditmgr.logout=Audit: Audit Module {0} threw the following exception during logout:
+auditmgr.loaderror=Audit: Cannot load AuditModule = {0}
+auditmgr.badinit=Audit: Cannot load Audit Module Initialization information. AuditModules will not be loaded.
+auditmgr.serverStartup=Audit: Audit Module {0} threw the following exception during server startup :
+auditmgr.serverShutdown=Audit: Audit Module {0} threw the following exception during server shutdown :
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatus.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatus.java
new file mode 100644
index 0000000..4e7c22c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatus.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+/**
+ * This interface stores the status of the authentication.
+ * @author Harish Prabandham
+ */
+
+public interface AuthenticationStatus extends java.io.Serializable {
+ public static final int AUTH_SUCCESS = 0; // Authentication Successful
+ public static final int AUTH_FAILURE = 1; // Authentication Failed
+ public static final int AUTH_CONTINUE = 2; // Continue the Authentication
+ public static final int AUTH_EXPIRED = 3; // Credentials have expired.
+
+ /**
+ * This method returns the status of the authentication
+ * @return An integer value indicating the status of the authentication
+ */
+ public int getStatus();
+
+ /**
+ * This is the value returned by the Authenticator when the status
+ * is AUTH_CONTINUE. This data should give an indication to the
+ * client on what else it should send to the server to complete the
+ * authentication.
+ *
+ * @return An array of bytes indicating the additional information
+ * needed to complete the authentication.
+ */
+ public byte[] getContinuationData();
+
+ /**
+ * This is the value returned by the Authenticator when the status
+ * is AUTH_CONTINUE. This data should give an indication to the
+ * client on specific authentication it needs to adopt to continue
+ * on with the authentication.
+ *
+ * @return An array of bytes indicating the authentication specific
+ * information needed to complete the authentication.
+ */
+ public byte[] getAuthSpecificData();
+}
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatusImpl.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatusImpl.java
new file mode 100644
index 0000000..cc3b893
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/AuthenticationStatusImpl.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+/**
+ * This class implements an AuthenticationStatus object.
+ * @author Harish Prabandham
+ */
+
+public class AuthenticationStatusImpl implements AuthenticationStatus {
+ private String realmName; // Name of the Realm
+ private String authMethod; // Method used for Authentication.
+ private String principalName; // String form of the Principal.
+ private int status; // Status
+
+ /**
+ * This constructs a new AuthenticationStatus object.
+ * @param The name of the principal
+ * @param The name of the realm that authenticated the principal
+ * @param The method used for authenticating the principal
+ * @param The status of the authentication
+ */
+ public AuthenticationStatusImpl(String principalName, String authMethod,
+ String realm,
+ int status) {
+ this.principalName = principalName;
+ this.authMethod = authMethod;
+ this.status = status;
+ this.realmName = realm;
+ }
+
+ /**
+ * This method returns the status of the authentication
+ * @return An integer value indicating the status of the authentication
+ */
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * This method returns a byte array of zero length, since there's
+ * no continuation data needed for passphrase based authentication.
+ * @return A byte array of zero length.
+ */
+ public byte[] getContinuationData() {
+ return new byte[0];
+ }
+
+ /**
+ * This method returns a byte array of zero length, since there's
+ * no auth specific data needed for passphrase based authentication.
+ * @return A byte array of zero length.
+ */
+ public byte[] getAuthSpecificData() {
+ return new byte[0];
+ }
+
+ /**
+ * This method returns the name of realm where the authentication was
+ * performed.
+ * @return A java.lang.String representation of the realm.
+ */
+ public String getRealmName() {
+ return realmName;
+ }
+
+ /**
+ * This method returns the "method" used to perform authentication
+ * @return A java.lang.String representation of the method used. In
+ * passphrase based authentication it returns the string "password".
+ */
+ public String getAuthMethod() {
+ return authMethod;
+ }
+
+ /**
+ * This method returns the string representation of the principal
+ * that was authenticated.
+ * @return A java.lang.String representation of the Principal.
+ */
+ public String getPrincipalName() {
+ return principalName;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/LocalStrings.properties
new file mode 100644
index 0000000..645fe87
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/LocalStrings.properties
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+#Sounds like unused file
+realmtool.username=Enter Username:
+realmtool.options= Options:
+realmtool.name=realm-name
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrincipalMapper.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrincipalMapper.java
new file mode 100644
index 0000000..1b3b705
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrincipalMapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import java.security.Principal;
+import java.util.Properties;
+
+/**
+ *
+ * Enables formatting of principal retrieved from message eg: P-Asserted-Identity values.
+ * eg: "Cullen Jennings" <sip:fluffy@cisco.com> value can be mapped/formatted to
+ * "CullenJ".
+ * @author k.venugopal@sun.com
+ */
+
+public interface PrincipalMapper {
+
+ public void initialize(Properties props);
+ /**
+ *
+ * converts values in to a format understood by the container/container backend eg: database, ldap etc.
+ *
+ * @param assrtId P-Asserted-Identity values.
+ * @return P-Asserted-Identity values in a format understood by the container.
+ */
+ public Principal[] mapIdentity(Principal[] assrtId);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/Privilege.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/Privilege.java
new file mode 100644
index 0000000..e2b7295
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/Privilege.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import java.rmi.*;
+
+/**
+ * This remote interface enables the deployment tool to query the
+ * details of the Privilege.
+ * @author Harish Prabandham
+ */
+public interface Privilege extends java.io.Serializable {
+ /**
+ * Returns the name of the name of the Privilege.
+ * @return The name of the name of the Privilege.
+ */
+ public String getName();
+}
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrivilegeImpl.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrivilegeImpl.java
new file mode 100644
index 0000000..92ce3b0
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/PrivilegeImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import java.rmi.*;
+
+
+/**
+ * This method provides an implementation a Privilege
+ * @author Harish Prabandham
+ */
+
+public class PrivilegeImpl implements Privilege {
+ private String name;
+
+ /**
+ * Creates a new Privilege object..
+ *
+ */
+ public PrivilegeImpl(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the hashCode ..
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * Returns the name of the name of the Privilege.
+ * @return The name of the name of the Privilege.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Compares equality...
+ */
+ public boolean equals(Object obj) {
+ if(obj instanceof Privilege) {
+ Privilege priv = (Privilege) obj;
+ return getName().equals(priv.getName());
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/RemoteObject.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/RemoteObject.java
new file mode 100644
index 0000000..f807d83
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/RemoteObject.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import com.sun.enterprise.util.*;
+import javax.rmi.PortableRemoteObject;
+import javax.rmi.CORBA.Tie;
+import org.omg.CORBA.ORB;
+
+/**
+ * Just a Base class to make exporting remote objects a bit easier...
+ * @author Harish Prabandham
+ */
+
+public class RemoteObject {
+ private ORB orb;
+
+ protected RemoteObject() {
+ //TODO:V3 commented, uncomment later orb = ORBManager.getORB();
+ }
+
+ protected void exportObject(java.rmi.Remote remote)
+ throws java.rmi.RemoteException {
+ // create servant and tie
+ PortableRemoteObject.exportObject(remote);
+ Tie servantsTie = javax.rmi.CORBA.Util.getTie(remote);
+
+ // Note: at this point the Tie doesnt have a delegate inside it,
+ // so it is not really "exported".
+ // The following call does orb.connect() which is the real exporting
+ servantsTie.orb(orb);
+ }
+
+ java.rmi.Remote getStub(java.rmi.Remote remote)
+ throws java.rmi.RemoteException {
+ return PortableRemoteObject.toStub(remote);
+ }
+}
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TimestampValidator.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TimestampValidator.java
new file mode 100644
index 0000000..ff862bc
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TimestampValidator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import java.util.Date;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * validate Timestamp received in messages.
+ * @author k.venugopal@sun.com
+ */
+public interface TimestampValidator {
+
+ /**
+ * validate given time against current time.
+ * @param created created time
+ * @param maxClockSkew maximum difference allowed between the system clocks of the sender and recipient.
+ * @param freshnessLimit maximum duration of time after which the Timestamp becomes stale
+ * @throws java.util.concurrent.TimeoutException
+ */
+ void validate(Date created,long maxClockSkew,long freshnessLimit)throws TimeoutException;
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TrustHandler.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TrustHandler.java
new file mode 100644
index 0000000..d3dbf13
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/TrustHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth;
+
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+/**
+ *
+ * Enables developers to provide custom implementation to enable sip containers
+ * to determine if a network entity can be trusted.
+ */
+public interface TrustHandler {
+
+
+ public void initialize(Properties props);
+ /**
+ * determines if the container can trust the network entity from which we received the message with P-Asserted-Identity
+ * header. This method also validates if the identity that was used to secure(eg: SSL) the message is trusted.
+ *
+ * @param pAssertedValues P-Asserted-Identity header values
+ * @param messageDirection "Incoming" if this method is invoked for a incoming request, "Outgoing" if the message is being sent out.
+ * @param asserterAddress ipaddress/hostname of the network entity from which we received the SIP message
+ * with P-Asserted-Identity header. Inorder to accept/use the values in P-Asserted-Identity
+ * header the network entity should be a trusted.
+ * @param securityid is the asserting security identity, if a secure connection is used then this
+ * would be the java.security.cert.X509Certificate, else null.
+ * @return true if we trust the networtid and the securityid.
+ */
+ public boolean isTrusted(String asserterAddress, String messageDirection,X509Certificate securityid, Principal[] pAssertedValues);
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Constants.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Constants.java
new file mode 100644
index 0000000..b50da7d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Constants.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.digest.api;
+
+/**
+ *
+ * @author K.Venugopal@sun.com
+ */
+public final class Constants {
+
+ public static final String NONCE = "nonce";
+ public static final String NONCE_COUNT = "nc";
+ public static final String CNONCE = "cnonce";
+ public static final String QOP = "qop";
+ public static final String METHOD = "method";
+ public static final String URI = "uri";
+ public static final String ALGORITHM = "algorithm";
+ public static final String ENTITY_BODY = "entityBody";
+ public static final String RESPONSE = "response";
+ public static final String DATA = "data";
+ public static final String A1 = "A1";
+ public static final String A2 = "A2";
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/DigestAlgorithmParameter.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/DigestAlgorithmParameter.java
new file mode 100644
index 0000000..b69737b
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/DigestAlgorithmParameter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.digest.api;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * Interface to Digest algorithm parameters
+ * @author K.Venugopal@sun.com
+ */
+public interface DigestAlgorithmParameter extends AlgorithmParameterSpec {
+ /**
+ * @returns the delimiter to be used while performing digest calculation, null otherwise.
+ *
+ */
+ public byte[] getDelimiter();
+ /**
+ *
+ * @returns the parameter value.
+ */
+ public byte[] getValue() ;
+ /**
+ * @returns the digest algorithm to be used.eg: MD5,MD5-sess etc..
+ *
+ */
+ public String getAlgorithm();
+ /**
+ * @returns the name of the parameter, null if no name is present.
+ */
+ public String getName();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Key.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Key.java
new file mode 100644
index 0000000..57c7895
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Key.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.digest.api;
+
+/**
+ * Represents the Key(username+realmname+passwd) to be used in the Digest calculation.
+ * Password is to be obtained from the store using the Key to complete the digest
+ * calculation.
+ *
+ * @author K.Venugopal@sun.com
+ */
+public interface Key {
+
+
+ public java.lang.String getRealmName();
+
+ public java.lang.String getUsername();
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/NestedDigestAlgoParam.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/NestedDigestAlgoParam.java
new file mode 100644
index 0000000..2ecc498
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/NestedDigestAlgoParam.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.digest.api;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * Interface representing nested DigestAlgorithm parameter values
+ * @author K.Venugopal@sun.com
+ */
+public interface NestedDigestAlgoParam extends DigestAlgorithmParameter{
+ /**
+ * @returns array of parameter values.
+ */
+ public AlgorithmParameterSpec[] getNestedParams();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Password.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Password.java
new file mode 100644
index 0000000..6471014
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/api/Password.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.digest.api;
+
+/**
+ * represents plain text password and pre hashed(username+realmname+password) password.
+ * @author K.Venuopal@sun.com
+ */
+public interface Password {
+ public static final int PLAIN_TEXT= 0;
+ public static final int HASHED = 1;
+ /**
+ * returns PLAIN_TEXT or HASHED.
+ * @returns int
+ */
+ public int getType();
+ /**
+ * returns password.
+ * @returns byte[]
+ */
+ public byte[] getValue();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/impl/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/impl/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/digest/impl/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/AssertedCredentials.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/AssertedCredentials.java
new file mode 100755
index 0000000..81683f2
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/AssertedCredentials.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+/**
+ *
+ * @author K.Venugopal@sun.com
+ */
+
+public class AssertedCredentials {
+
+ private String realmName = "";
+ private String userName = "";
+ private Object info = null;
+
+ public AssertedCredentials(String realmName,String userName) {
+ this.realmName = realmName;
+ this.userName = userName;
+ }
+
+ public AssertedCredentials(String realmName,String userName,Object info) {
+ this.realmName = realmName;
+ this.userName = userName;
+ this.info = info;
+ }
+
+ public String getRealmName(){
+ return realmName;
+ }
+
+ public String getUserName(){
+ return userName;
+ }
+
+ public Object getInfo(){
+ return info;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientCertificateLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientCertificateLoginModule.java
new file mode 100644
index 0000000..9762ff5
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientCertificateLoginModule.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.auth.login.common.X509CertificateCredential;
+import java.util.Map;
+import java.util.Enumeration;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+//V3:Commented import com.sun.enterprise.config.clientbeans.Ssl;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import com.sun.enterprise.security.integration.AppClientSSL;
+
+import org.glassfish.security.common.PrincipalImpl;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import java.util.logging.*;
+import com.sun.logging.*;
+import org.glassfish.internal.api.Globals;
+
+
+/**
+ * <p> This LoginModule authenticates users with X509 certificates.
+ *
+ * <p> If testUser successfully authenticates itself,
+ * a <code>PrincipalImpl</code> with the testUser's username
+ * is added to the Subject.
+ *
+ * <p> This LoginModule recognizes the debug option.
+ * If set to true in the login Configuration,
+ * debug messages will be output to the output stream, System.out.
+ *
+ * @author Harpreet Singh (harpreet.singh@sun.com)
+ */
+
+public class ClientCertificateLoginModule implements LoginModule {
+
+ private static Logger _logger=null;
+ static {
+ _logger=SecurityLoggerInfo.getLogger();
+ }
+
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ClientCertificateLoginModule.class);
+
+ private static KeyStore ks = null;
+
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map sharedState;
+ private Map options;
+
+ // configurable option
+ private boolean debug = false; // default
+
+ // the authentication status
+ private boolean succeeded = false;
+ private boolean commitSucceeded = false;
+
+ private String alias;
+ private X509Certificate certificate;
+
+ // testUser's PrincipalImpl
+ private PrincipalImpl userPrincipal;
+
+ private AppClientSSL ssl;
+ private SSLUtils sslUtils;
+
+ /**
+ * Initialize this <code>LoginModule</code>.
+ *
+ * <p>
+ *
+ * @param subject the <code>Subject</code> to be authenticated. <p>
+ *
+ * @param callbackHandler a <code>CallbackHandler</code> for communicating
+ * with the end user (prompting for usernames and
+ * passwords, for example). <p>
+ *
+ * @param sharedState shared <code>LoginModule</code> state. <p>
+ *
+ * @param options options specified in the login
+ * <code>Configuration</code> for this particular
+ * <code>LoginModule</code>.
+ */
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options) {
+
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+
+ // initialize any configured options
+ debug = "true".equalsIgnoreCase((String)options.get("debug"));
+ sslUtils = Globals.getDefaultHabitat().getService(SSLUtils.class);
+ }
+
+
+ /**
+ * Authenticate the user by prompting for a username and password.
+ *
+ * <p>
+ *
+ * @return true in all cases since this <code>LoginModule</code>
+ * should not be ignored.
+ *
+ * @exception LoginException if this <code>LoginModule</code>
+ * is unable to perform the authentication.
+ */
+ public boolean login() throws LoginException {
+
+ // prompt for a username and password
+ if (callbackHandler == null){
+ throw new LoginException("Error: no CallbackHandler available " +
+ "to garner authentication information from the user");
+ }
+
+ try {
+ String[] as = new String[ks.size()];
+ String[] aliasString = new String[ks.size()];
+ Enumeration aliases = ks.aliases();
+ for(int i = 0; i < ks.size(); i++) {
+ aliasString[i] = (String) aliases.nextElement();
+ as[i] = ((X509Certificate)ks.getCertificate(aliasString[i])).getSubjectDN().getName();
+ }
+
+ Callback[] callbacks = new Callback[1];
+ callbacks[0] = new ChoiceCallback(localStrings.getLocalString("login.certificate", "Choose from list of certificates: "), as, 0, false);
+
+ callbackHandler.handle(callbacks);
+
+ int[] idx = ((ChoiceCallback)callbacks[0]).getSelectedIndexes();
+
+ if (idx == null) {
+ throw new LoginException ("No certificate selected!");
+ } else if (idx[0] == -1){
+ throw new LoginException ("Incorrect keystore password");
+ }
+ // print debugging information
+ if (debug) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
+ "user entered certificate: ");
+ for (int i = 0; i < idx.length; i++){
+ _logger.log(Level.FINE,aliasString[idx[i]]);
+ }
+ }
+ }
+
+ // the authenticate method previously picked out the
+ // wrong alias.
+ // since we allow only 1 choice the first element in idx
+ // idx[0] should have the selected index.
+ this.alias = aliasString[idx[0]];
+ certificate = (X509Certificate) ks.getCertificate(alias);
+ // the authenticate should always return a true.
+ if (debug){
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
+ "authentication succeeded");
+ }
+ }
+ succeeded = true;
+ return true;
+ } catch (java.io.IOException ioe) {
+ throw new LoginException(ioe.toString());
+ } catch (UnsupportedCallbackException uce) {
+ throw new LoginException("Error: " + uce.getCallback().toString() +
+ " not available to garner authentication information " +
+ "from the user");
+ } catch (Exception e) {
+ throw new LoginException(e.toString());
+ }
+ }
+ /**
+ * <p> This method is called if the LoginContext's
+ * overall authentication succeeded
+ * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
+ * succeeded).
+ *
+ * <p> If this LoginModule's own authentication attempt
+ * succeeded (checked by retrieving the private state saved by the
+ * <code>login</code> method), then this method associates a
+ * <code>PrincipalImpl</code>
+ * with the <code>Subject</code> located in the
+ * <code>LoginModule</code>. If this LoginModule's own
+ * authentication attempted failed, then this method removes
+ * any state that was originally saved.
+ *
+ * <p>
+ *
+ * @exception LoginException if the commit fails.
+ *
+ * @return true if this LoginModule's own login and commit
+ * attempts succeeded, or false otherwise.
+ */
+ public boolean commit() throws LoginException {
+ if (succeeded == false) {
+ return false;
+ } else {
+ // add a Principal (authenticated identity)
+ // to the Subject
+
+ // assume the user we authenticated is the PrincipalImpl
+ userPrincipal = new PrincipalImpl(alias);
+ if (!subject.getPrincipals().contains(userPrincipal)){
+ subject.getPrincipals().add(userPrincipal);
+ }
+
+ if (debug) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"\t\t[ClientCertificateLoginModule] " +
+ "added PrincipalImpl to Subject");
+ }
+ }
+
+ ssl = new AppClientSSL();
+ ssl.setCertNickname(this.alias);
+ sslUtils.setAppclientSsl(ssl);
+
+ String realm = LoginContextDriver.CERT_REALMNAME;
+ X509Certificate[] certChain = new X509Certificate[1];
+ certChain[0] = certificate;
+ X509CertificateCredential pc =
+ new X509CertificateCredential(certChain, alias, realm);
+ if(!subject.getPrivateCredentials().contains(pc)) {
+ subject.getPrivateCredentials().add(pc);
+ }
+
+ commitSucceeded = true;
+ return true;
+ }
+ }
+
+ /**
+ * <p> This method is called if the LoginContext's
+ * overall authentication failed.
+ * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
+ * did not succeed).
+ *
+ * <p> If this LoginModule's own authentication attempt
+ * succeeded (checked by retrieving the private state saved by the
+ * <code>login</code> and <code>commit</code> methods),
+ * then this method cleans up any state that was originally saved.
+ *
+ * <p>
+ *
+ * @exception LoginException if the abort fails.
+ *
+ * @return false if this LoginModule's own login and/or commit attempts
+ * failed, and true otherwise.
+ */
+ public boolean abort() throws LoginException {
+ if (succeeded == false) {
+ return false;
+ } else if (succeeded == true && commitSucceeded == false) {
+ // login succeeded but overall authentication failed
+ succeeded = false;
+ alias = null;
+ userPrincipal = null;
+ } else {
+ // overall authentication succeeded and commit succeeded,
+ // but someone else's commit failed
+ logout();
+ }
+ return true;
+ }
+
+ /**
+ * Logout the user.
+ *
+ * <p> This method removes the <code>PrincipalImpl</code>
+ * that was added by the <code>commit</code> method.
+ *
+ * <p>
+ *
+ * @exception LoginException if the logout fails.
+ *
+ * @return true in all cases since this <code>LoginModule</code>
+ * should not be ignored.
+ */
+ public boolean logout() throws LoginException {
+ // unset the alias
+ ssl = null;
+ sslUtils.setAppclientSsl(ssl);
+ subject.getPrincipals().remove(userPrincipal);
+ succeeded = false;
+ commitSucceeded = false;
+ alias = null;
+ userPrincipal = null;
+ return true;
+ }
+
+ public static void setKeyStore(KeyStore keyStore) {
+ ks = keyStore;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientPasswordLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientPasswordLoginModule.java
new file mode 100644
index 0000000..2dee6c8
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/ClientPasswordLoginModule.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import java.util.*;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import org.glassfish.security.common.PrincipalImpl;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import java.util.logging.*;
+import com.sun.logging.*;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.UsernamePasswordStore;
+
+/**
+ * <p> This sample LoginModule authenticates users with a password.
+ *
+ * <p> If testUser successfully authenticates itself,
+ * a <code>PrincipalImpl</code> with the testUser's username
+ * is added to the Subject.
+ *
+ * @author Harpreet Singh (harpreet.singh@sun.com)
+ */
+
+public class ClientPasswordLoginModule implements LoginModule {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ private static final String DEFAULT_REALMNAME = "default";
+ private static final LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ClientPasswordLoginModule.class);
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map sharedState;
+ private Map options;
+
+ // the authentication status
+ private boolean succeeded = false;
+ private boolean commitSucceeded = false;
+
+ // username and password
+ private String username;
+ private char[] password;
+
+ // testUser's PrincipalImpl
+ private PrincipalImpl userPrincipal;
+ public static final String LOGIN_NAME = "j2eelogin.name";
+ public static final String LOGIN_PASSWORD = "j2eelogin.password";
+
+
+ /**
+ * Initialize this <code>LoginModule</code>.
+ *
+ * <p>
+ *
+ * @param subject the <code>Subject</code> to be authenticated. <p>
+ *
+ * @param callbackHandler a <code>CallbackHandler</code> for communicating
+ * with the end user (prompting for usernames and
+ * passwords, for example). <p>
+ *
+ * @param sharedState shared <code>LoginModule</code> state. <p>
+ *
+ * @param options options specified in the login
+ * <code>Configuration</code> for this particular
+ * <code>LoginModule</code>.
+ */
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+
+ }
+
+ /**
+ * Authenticate the user by prompting for a username and password.
+ *
+ * <p>
+ *
+ * @return true in all cases since this <code>LoginModule</code>
+ * should not be ignored.
+ *
+ * @exception FailedLoginException if the authentication fails. <p>
+ *
+ * @exception LoginException if this <code>LoginModule</code>
+ * is unable to perform the authentication.
+ */
+ public boolean login() throws LoginException {
+
+ // prompt for a username and password
+ if (callbackHandler == null){
+ String failure = localStrings.getLocalString("login.nocallback","Error: no CallbackHandler available to garner authentication information from the user");
+ throw new LoginException(failure);
+ }
+
+ // Get the username from the exchange mechanism
+ String uname = UsernamePasswordStore.getUsername();
+ char[] pswd = UsernamePasswordStore.getPassword();
+ boolean doSet = false;
+
+ // bugfix# 6412539
+ if (uname == null) {
+ uname = System.getProperty(LOGIN_NAME);
+ doSet = true;
+ }
+ if (pswd == null) {
+ if(System.getProperty(LOGIN_PASSWORD) != null) {
+ pswd = System.getProperty(LOGIN_PASSWORD).toCharArray();
+ }
+ doSet = true;
+ }
+
+ if (doSet) {
+ UsernamePasswordStore.set(uname, pswd);
+ }
+
+ if (uname != null && pswd != null) {
+ username = uname;
+
+ int length = pswd.length;
+ password = new char[length];
+ System.arraycopy (pswd, 0, password, 0,length);
+ } else{
+ Callback[] callbacks = new Callback[2];
+ NameCallback nameCB = new NameCallback(localStrings.getLocalString("login.username", "ClientPasswordModule username"));
+ String defaultUname = System.getProperty("user.name");
+ if (defaultUname != null) {
+ nameCB = new NameCallback(localStrings.getLocalString("login.username", "ClientPasswordModule username"),defaultUname);
+ }
+ callbacks[0] = nameCB;
+ callbacks[1] = new PasswordCallback(localStrings.getLocalString("login.password", "ClientPasswordModule password: "), false);
+
+ try {
+ callbackHandler.handle(callbacks);
+ username = ((NameCallback)callbacks[0]).getName();
+ if(username == null){
+ String fail = localStrings.getLocalString("login.nousername", "No user specified");
+ throw new LoginException(fail);
+ }
+ char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
+ if (tmpPassword == null) {
+ // treat a NULL password as an empty password
+ tmpPassword = new char[0];
+ }
+ password = new char[tmpPassword.length];
+ System.arraycopy(tmpPassword, 0,
+ password, 0, tmpPassword.length);
+ ((PasswordCallback)callbacks[1]).clearPassword();
+
+ } catch (java.io.IOException ioe) {
+ throw new LoginException(ioe.toString());
+ } catch (UnsupportedCallbackException uce) {
+ String nocallback = localStrings.getLocalString("login.callback","Error: Callback not available to garner authentication information from user(CallbackName):" );
+ throw new LoginException(nocallback +
+ uce.getCallback().toString());
+ }
+ }
+
+ // by default - the client side login module will always say
+ // that the login successful. The actual login will take place
+ // on the server side.
+
+ _logger.log(Level.FINEST,"\t\t[ClientPasswordLoginModule] " +
+ "authentication succeeded");
+ succeeded = true;
+ return true;
+ }
+
+
+ /**
+ * <p> This method is called if the LoginContext's
+ * overall authentication succeeded
+ * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
+ * succeeded).
+ *
+ * <p> If this LoginModule's own authentication attempt
+ * succeeded (checked by retrieving the private state saved by the
+ * <code>login</code> method), then this method associates a
+ * <code>PrincipalImpl</code>
+ * with the <code>Subject</code> located in the
+ * <code>LoginModule</code>. If this LoginModule's own
+ * authentication attempted failed, then this method removes
+ * any state that was originally saved.
+ *
+ * <p>
+ *
+ * @exception LoginException if the commit fails.
+ *
+ * @return true if this LoginModule's own login and commit
+ * attempts succeeded, or false otherwise.
+ */
+ public boolean commit() throws LoginException {
+ if (succeeded == false) {
+ return false;
+ } else {
+ // add a Principal (authenticated identity)
+ // to the Subject
+
+ // assume the user we authenticated is the PrincipalImpl
+ userPrincipal = new PrincipalImpl(username);
+ if (!subject.getPrincipals().contains(userPrincipal)){
+ subject.getPrincipals().add(userPrincipal);
+ }
+ _logger.log(Level.FINE,"\t\t[ClientPasswordLoginModule] " +
+ "added PrincipalImpl to Subject");
+
+ String realm = DEFAULT_REALMNAME;
+
+ PasswordCredential pc =
+ new PasswordCredential(username, password, realm);
+ if(!subject.getPrivateCredentials().contains(pc)) {
+ subject.getPrivateCredentials().add(pc);
+ }
+ // in any case, clean out state
+ username = null;
+ for (int i = 0; i < password.length; i++){
+ password[i] = ' ';
+ }
+ password = null;
+ commitSucceeded = true;
+ return true;
+ }
+ }
+
+ /**
+ * <p> This method is called if the LoginContext's
+ * overall authentication failed.
+ * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
+ * did not succeed).
+ *
+ * <p> If this LoginModule's own authentication attempt
+ * succeeded (checked by retrieving the private state saved by the
+ * <code>login</code> and <code>commit</code> methods),
+ * then this method cleans up any state that was originally saved.
+ *
+ * <p>
+ *
+ * @exception LoginException if the abort fails.
+ *
+ * @return false if this LoginModule's own login and/or commit attempts
+ * failed, and true otherwise.
+ */
+ public boolean abort() throws LoginException {
+ if (succeeded == false) {
+ return false;
+ } else if (succeeded == true && commitSucceeded == false) {
+ // login succeeded but overall authentication failed
+ succeeded = false;
+ username = null;
+ if (password != null) {
+ for (int i = 0; i < password.length; i++){
+ password[i] = ' ';
+ }
+ password = null;
+ }
+ userPrincipal = null;
+ } else {
+ // overall authentication succeeded and commit succeeded,
+ // but someone else's commit failed
+ logout();
+ }
+ return true;
+ }
+
+ /**
+ * Logout the user.
+ *
+ * <p> This method removes the <code>PrincipalImpl</code>
+ * that was added by the <code>commit</code> method.
+ *
+ * <p>
+ *
+ * @exception LoginException if the logout fails.
+ *
+ * @return true in all cases since this <code>LoginModule</code>
+ * should not be ignored.
+ */
+ public boolean logout() throws LoginException {
+
+ subject.getPrincipals().remove(userPrincipal);
+ succeeded = commitSucceeded;
+ username = null;
+ if (password != null) {
+ for (int i = 0; i < password.length; i++){
+ password[i] = ' ';
+ }
+ password = null;
+ }
+ userPrincipal = null;
+ return true;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DigestCredentials.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DigestCredentials.java
new file mode 100755
index 0000000..4551e75
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DigestCredentials.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+import com.sun.enterprise.security.auth.digest.api.DigestAlgorithmParameter;
+
+/**
+ *
+ * @author K.Venugopal@sun.com
+ */
+public class DigestCredentials {
+
+ private String realmName = "";
+ private String username = "";
+ private DigestAlgorithmParameter [] params = null;
+
+ public DigestCredentials(String realmName, String username,DigestAlgorithmParameter [] params) {
+ this.realmName = realmName;
+ this.username = username;
+ this.params = params;
+ }
+
+ public String getRealmName() {
+ return this.realmName;
+ }
+
+ public String getUserName() {
+ return this.username;
+ }
+
+ public DigestAlgorithmParameter [] getParameters(){
+ return params;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DistinguishedPrincipalCredential.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DistinguishedPrincipalCredential.java
new file mode 100644
index 0000000..90aa80e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/DistinguishedPrincipalCredential.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import java.security.Principal;
+
+public class DistinguishedPrincipalCredential {
+ private Principal prin = null;
+
+ public DistinguishedPrincipalCredential(Principal prin) {
+ this.prin = prin;
+ }
+
+ public Principal getPrincipal() {
+ return prin;
+ }
+
+ public String toString() {
+ return "DistingushedPrincipal: " + prin;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/FileLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/FileLoginModule.java
new file mode 100644
index 0000000..2fe4fee
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/FileLoginModule.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import java.util.*;
+import java.util.logging.Level;
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import javax.security.auth.login.LoginException;
+
+/**
+ * File realm login module.
+ *
+ * <P>Provides a file-based implementation of a password login module.
+ * Processing is delegated to the FileRealm class.
+ *
+ * @see com.sun.enterprise.security.auth.login.PasswordLoginModule
+ * @see com.sun.enterprise.security.auth.realm.file.FileRealm
+ *
+ */
+public class FileLoginModule extends PasswordLoginModule
+{
+
+ /**
+ * Perform file authentication. Delegates to FileRealm.
+ *
+ * @throws LoginException If login fails (JAAS login() behavior).
+ *
+ */
+ protected void authenticate()
+ throws LoginException
+ {
+ if (!(_currentRealm instanceof FileRealm)) {
+ String msg = sm.getString("filelm.badrealm");
+ throw new LoginException(msg);
+ }
+ FileRealm fileRealm = (FileRealm)_currentRealm;
+
+ String[] grpList = fileRealm.authenticate(_username, getPasswordChar());
+
+ if (grpList == null) { // JAAS behavior
+ String msg = sm.getString("filelm.faillogin", _username);
+ throw new LoginException(msg);
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "File login succeeded for: " + _username);
+ }
+
+ commitAuthentication(_username, getPasswordChar(),
+ _currentRealm, grpList);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LDAPLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LDAPLoginModule.java
new file mode 100644
index 0000000..44ffd5d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LDAPLoginModule.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+
+import com.sun.enterprise.security.auth.login.PasswordLoginModule;
+import javax.security.auth.login.*;
+
+import com.sun.enterprise.security.auth.realm.ldap.LDAPRealm;
+
+/**
+ * iAS JAAS LoginModule for an LDAP Realm.
+ *
+ * <P>Refer to the LDAPRealm documentation for necessary and optional
+ * configuration parameters for the iAS LDAP login support.
+ *
+ * <P>There are various ways in which a user can be authenticated using
+ * an LDAP directory. Currently this login module only supports one mode,
+ * 'find and bind'. Other modes may be added as schedules permit.
+ *
+ * <P>Mode: <i>find-bind</i>
+ * <ol>
+ * <li>An LDAP search is issued on the directory starting at base-dn
+ * with the given search-filter (having substituted the user name
+ * in place of %s). If no entries match this search, login fails
+ * and authentication is over.
+ * <li>The DN of the entry which matched the search as the DN
+ * of the user in the directory. If the search-filter
+ * is properly set there should always be a single match; if there are
+ * multiple matches, the first one found is used.
+ * <li>Next an LDAP bind is attempted using the above DN and the provided
+ * password. If this fails, login is considered to have failed and
+ * authentication is over.
+ * <li>Then an LDAP search is issued on the directory starting at
+ * group-base-dn with the given group-search-filter (having
+ * substituted %d for the user DN previously found). From the
+ * matched entry(ies) all the values of group-target are taken
+ * as group names in which the user has membership. If no entries
+ * are found, the group membership is empty.
+ * </ol>
+ *
+ *
+ */
+public class LDAPLoginModule extends PasswordLoginModule
+{
+ private LDAPRealm _ldapRealm;
+
+ /**
+ * Performs authentication for the current user.
+ *
+ */
+ protected void authenticate ()
+ throws LoginException
+ {
+ if (!(_currentRealm instanceof LDAPRealm)) {
+ String msg = sm.getString("ldaplm.badrealm");
+ throw new LoginException(msg);
+ }
+ _ldapRealm = (LDAPRealm)_currentRealm;
+
+ // enforce that password cannot be empty.
+ // ldap may grant login on empty password!
+ if (getPasswordChar() == null || getPasswordChar().length == 0) {
+ String msg = sm.getString("ldaplm.emptypassword", _username);
+ throw new LoginException(msg);
+ }
+
+ String mode = _currentRealm.getProperty(LDAPRealm.PARAM_MODE);
+
+ if (LDAPRealm.MODE_FIND_BIND.equals(mode)) {
+ String[] grpList = _ldapRealm.findAndBind(_username, getPasswordChar());
+ commitAuthentication(_username, getPasswordChar(),
+ _currentRealm, grpList);
+ } else {
+ String msg = sm.getString("ldaplm.badmode", mode);
+ throw new LoginException(msg);
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LocalStrings.properties
new file mode 100644
index 0000000..ecb1868
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LocalStrings.properties
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+login.user=user
+login.username=Enter Username
+login.password=Enter Password:
+login.certificate=Choose from the list of certificates:
+login.nousername=No user specified
+login.nocallback=Error: Callback not available to garner authentication information from user(CallbackName):
+pwdlm.noinfo=Missing Subject information for Login.
+pwdlm.nocreds=No credentials.
+pwdlm.norealm=No realm {0}.
+## No realm available for {requested realm}.
+pwdlm.norealmavail=No realm available for {0}.
+solarislm.badrealm=SolarisLoginModule requires SolarisRealm.
+solarislm.nulluser=Login failed for null user.
+solarislm.loginfail=Failed solaris login for {0}.
+ldaplm.badrealm=LDAPLoginModule requires LDAPRealm.
+ldaplm.badmode=Unsupported mode {0}.
+ldaplm.usernotfound=User {0} not found.
+ldaplm.emptypassword=Access denied on empty password for user {0}.
+filelm.badrealm=FileLoginModule requires FileRealm.
+filelm.faillogin=Failed file login for {0}.
+jdbclm.badrealm=JDBCLoginModule requires JDBCRealm.
+jdbclm.nulluser=Login failed for null user.
+jdbclm.loginfail=Failed jdbc login for {0}.
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginCallbackHandler.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginCallbackHandler.java
new file mode 100644
index 0000000..cc05717
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginCallbackHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import java.io.*;
+import javax.security.auth.callback.*;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.security.TextLoginDialog;
+import com.sun.enterprise.security.GUILoginDialog;
+
+/**
+ * This is the default callback handler provided by the application
+ * client container. The container tries to use the application specified
+ * callback handler (if provided). If there is no callback handler or if
+ * the handler cannot be instantiated then this default handler is used.
+ *
+ * Note: User-defined Callback Handlers which intend to indicate cancel
+ * status must extend this class and set the ThreadLocal cancelStatus.
+ */
+public class LoginCallbackHandler implements CallbackHandler
+{
+ private boolean isGUI;
+ private static final LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(LoginCallbackHandler.class);
+ protected ThreadLocal<Boolean> cancelStatus = new ThreadLocal<Boolean>();
+
+ /**
+ * Check whether the authentication was cancelled by the user.
+ * @return boolean indicating whether the authentication was cancelled.
+ */
+ public boolean getCancelStatus() {
+ boolean cancelled = cancelStatus.get();
+ cancelStatus.set(false);
+ return cancelled;
+ }
+
+ public LoginCallbackHandler() {
+ this(true);
+ }
+
+ public LoginCallbackHandler(boolean gui) {
+ isGUI = gui;
+ cancelStatus.set(false);
+ }
+
+ /**
+ * This is the callback method called when authentication data is
+ * required. It either pops up a dialog box to request authentication
+ * data or use text input.
+ * @param the callback object instances supported by the login module.
+ */
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException
+ {
+ if(isGUI) {
+ String user = localStrings.getLocalString("login.user", "user");
+ new GUILoginDialog(user, callbacks);
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ cancelStatus.set(((NameCallback) callbacks[i]).getName() == null);
+ break;
+ }
+ }
+ } else {
+ new TextLoginDialog(callbacks);
+ }
+ }
+}
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginContextDriver.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginContextDriver.java
new file mode 100644
index 0000000..2926a94
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/LoginContextDriver.java
@@ -0,0 +1,1075 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import org.glassfish.security.common.Group;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Enumeration;
+import java.security.Principal;
+import java.util.logging.*;
+import java.security.PrivilegedAction;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.x500.X500Principal;
+import sun.security.x509.X500Name;
+import com.sun.logging.*;
+import com.sun.enterprise.common.iiop.security.GSSUPName;
+import com.sun.enterprise.common.iiop.security.AnonCredential;
+import com.sun.enterprise.security.SecurityContext;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.SecurityServicesUtil;
+import com.sun.enterprise.security.audit.AuditManager;
+import com.sun.enterprise.security.common.AppservAccessController;
+//import com.sun.enterprise.security.SecurityContext;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import com.sun.enterprise.security.auth.login.common.X509CertificateCredential;
+import com.sun.enterprise.security.auth.login.common.ServerLoginCallbackHandler;
+import com.sun.enterprise.security.auth.login.common.LoginException;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
+
+// FIXME: ACC methods need to be moved to ACC-specific class.
+import com.sun.enterprise.security.auth.realm.InvalidOperationException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.common.ClientSecurityContext;
+//import com.sun.enterprise.appclient.AppContainer;
+import com.sun.enterprise.security.common.SecurityConstants;
+import org.glassfish.internal.api.Globals;
+
+
+/**
+ *
+ * This class is invoked implicitly by the server to log in the user
+ * information that was sent on the wire by the client. Clients will
+ * use the <i>doClientLogin</i> method to simulate authentication to the
+ * server.
+ *
+ * @author Harpreet Singh (hsingh@eng.sun.com)
+ * @author Jyri Virkki
+ *
+ */
+public class LoginContextDriver {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ private static final ServerLoginCallbackHandler
+ dummyCallback = new ServerLoginCallbackHandler();
+
+ // moved to SecurityConstants.
+// private static final String CLIENT_JAAS_PASSWORD = "default";
+// private static final String CLIENT_JAAS_CERTIFICATE = "certificate";
+
+ public static final String CERT_REALMNAME = "certificate";
+
+ private static volatile AuditManager AUDIT_MANAGER=null;
+
+ /** This class cannot be instantiated
+ *
+ */
+ private LoginContextDriver(){
+ }
+
+ private static AuditManager getAuditManager() {
+ if(AUDIT_MANAGER != null) {
+ return AUDIT_MANAGER;
+ }
+ return _getAuditManager();
+ }
+
+ private static synchronized AuditManager _getAuditManager() {
+ if(AUDIT_MANAGER == null) {
+ SecurityServicesUtil secServUtil = Globals.get(SecurityServicesUtil.class);
+ AUDIT_MANAGER = secServUtil.getAuditManager();
+ }
+ return AUDIT_MANAGER;
+ }
+
+ /**
+ * This method is just a convenience wrapper for
+ * <i>login(Subject, Class)</i> method. It will construct a
+ * PasswordCredential class.
+ *
+ * @param String username
+ * @param String password
+ * @param String realmName the name of the realm to login into, if realmName
+ * is null, we login into the default realm
+ */
+
+ public static void login(String username, char[] password, String realmName){
+
+ if(realmName == null || !(Realm.isValidRealm(realmName))){
+ realmName = Realm.getDefaultRealm();
+ }
+ final Subject fs = new Subject();
+ final PasswordCredential pc =
+ new PasswordCredential(username, password, realmName);
+
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ fs.getPrivateCredentials().add(pc);
+ return fs;
+ }
+ });
+
+ LoginContextDriver.login(fs, PasswordCredential.class);
+ }
+
+
+ public static void login(AssertedCredentials asrtCred) throws javax.security.auth.login.LoginException {
+ Subject subject = new Subject();
+ subject.getPrivateCredentials().add(asrtCred);
+ String jaasCtx = null;
+ try {
+ jaasCtx = Realm.getInstance(asrtCred.getRealmName()).getJAASContext();
+ } catch (Exception ex) {
+ if (ex instanceof LoginException) {
+ throw (LoginException) ex;
+ } else {
+ throw (LoginException) new LoginException(ex.toString()).initCause(ex);
+ }
+ }
+
+ try {
+ // A dummyCallback is used to satisfy JAAS but it is never used.
+ // name/pwd info is already contained in Subject's Credential
+ LoginContext lg = new LoginContext(jaasCtx, subject, dummyCallback);
+ lg.login();
+ } catch (Exception e) {
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.auditAtnRefusedError, asrtCred.getUserName());
+ }
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINEST, "doPasswordLogin fails", e);
+ }
+ if (AUDIT_MANAGER.isAuditOn()) {
+ AUDIT_MANAGER.authentication(asrtCred.getUserName(), asrtCred.getRealmName(), false);
+ }
+ if (e instanceof LoginException) {
+ throw (LoginException) e;
+ } else {
+ throw (LoginException) new LoginException("Login failed: " + e.getMessage()).initCause(e);
+ }
+ }
+
+ setSecurityContext(asrtCred.getUserName(), subject, asrtCred.getRealmName());
+ }
+
+
+ /**
+ * This method performs the login on the server side.
+ *
+ * <P>This method is the main login method for S1AS. It is called
+ * with a Subject and the type (class) of credential which should
+ * be checked. The Subject must contain a credential of the
+ * specified type or login will fail.
+ *
+ * <P>While the implementation has been cleaned up, the login
+ * process still consists of a number of special cases which are
+ * treated separately at the realm level. In the future tighter
+ * JAAS integration could clean some of this up.
+ *
+ * <P>The following credential types are recognized at this time:
+ * <ul>
+ * <li>PasswordCredential - This is the general case for all login
+ * methods which rely on the client providing a name and password.
+ * It can be used with any realms/JAAS login modules which expect
+ * such data (e.g. file realm, LDAP realm, UNIX realm)
+ * <LI>X509CertificateCredential - Special case for SSL client auth.
+ * Here authentication has already been done by the SSL subsystem
+ * so this login only creates a security context based on the
+ * certificate data.
+ * <LI>AnonCredential - Unauthenticated session, set anonymous security
+ * context.
+ * <LI>GSSUPName - Retrieve user and realm and set security context.
+ * <LI>X500Name - Retrieve user and realm and set security context.
+ * </ul>
+ *
+ * @param Subject the subject of the client
+ * @param Class the class of the credential packaged in the subject.
+ *
+ */
+ public static void login(Subject subject, Class cls)
+ throws LoginException
+ {
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINEST,
+ "Processing login with credentials of type: "+
+ cls.toString());
+ }
+
+ if(cls.equals(PasswordCredential.class)) {
+ doPasswordLogin(subject);
+
+ } else if (cls.equals(X509CertificateCredential.class)) {
+ doCertificateLogin(subject);
+
+ } else if (cls.equals(AnonCredential.class)) {
+ doAnonLogin();
+
+ } else if (cls.equals(GSSUPName.class)) {
+ doGSSUPLogin(subject);
+
+ } else if (cls.equals(X500Name.class)) {
+ doX500Login(subject, null);
+
+ } else {
+ _logger.log(Level.INFO, SecurityLoggerInfo.unknownCredentialError,
+ cls.toString());
+ throw new
+ LoginException("Unknown credential type, cannot login.");
+ }
+ }
+
+
+ /**
+ * This method is used for logging in a run As principal. It creates
+ * a JAAS subject whose credential is to type GSSUPName.
+ * This is used primarily for runas
+ *
+ */
+ public static void loginPrincipal(String username, String realmName)
+ throws LoginException {
+
+ // no realm provided, assuming default
+ if(realmName == null || realmName.length() == 0){
+ realmName = Realm.getDefaultRealm();
+ }
+
+ final Subject s = new Subject();
+
+ final org.glassfish.security.common.PrincipalImpl p
+ = new org.glassfish.security.common.PrincipalImpl(username);
+
+ final GSSUPName name = new GSSUPName(username, realmName);
+
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ s.getPrincipals().add(p);
+ s.getPublicCredentials().add(name);
+ return null;
+ }
+ });
+
+ try {
+ Realm realm = Realm.getInstance(realmName);
+ Enumeration en = realm.getGroupNames(username);
+ Set<Principal> principalSet = s.getPrincipals();
+ while (en.hasMoreElements()) {
+ principalSet.add(new Group((String) en.nextElement()));
+ }
+
+ } catch (InvalidOperationException ex) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.invalidOperationForRealmError, new Object[] { username, realmName, ex.toString()});
+ } catch (NoSuchUserException ex){
+ _logger.log(Level.WARNING, SecurityLoggerInfo.noSuchUserInRealmError, new Object[] { username, realmName, ex.toString()});
+ } catch (NoSuchRealmException ex) {
+ LoginException lex = new LoginException(ex.toString());
+ lex.initCause(ex);
+ throw lex;
+ }
+ setSecurityContext(username, s, realmName);
+ }
+
+
+ /**
+ * This method logs out the user by clearing the security context.
+ *
+ */
+ public static void logout() throws LoginException {
+ unsetSecurityContext();
+ }
+
+
+ /**
+ * Log in subject with PasswordCredential. This is a generic login
+ * which applies to all login mechanisms which process PasswordCredential.
+ * In other words, any mechanism which receives an actual username, realm
+ * and password set from the client.
+ *
+ * <P>The realm contained in the credential is checked, and a JAAS
+ * LoginContext is created using a context name obtained from the
+ * appropriate Realm instance. The applicable JAAS LoginModule
+ * is initialized (based on the jaas login configuration) and login()
+ * is invoked on it.
+ *
+ * <P>RI code makes several assumptions which are retained here:
+ * <ul>
+ * <li>The PasswordCredential is stored as a private credential of
+ * the subject.
+ * <li>There is only one such credential present (actually, only
+ * the first one is relevant if more are present).
+ * </ui>
+ *
+ * @param s Subject to be authenticated.
+ * @throws LoginException Thrown if the login fails.
+ *
+ */
+ private static void doPasswordLogin(Subject subject)
+ throws LoginException
+ {
+ final Subject s = subject;
+
+ Object obj = getPrivateCredentials(s, PasswordCredential.class);
+ assert obj != null;
+
+ PasswordCredential p = (PasswordCredential) obj;
+ String user = p.getUser();
+ char[] pwd = p.getPassword();
+ String realm = p.getRealm();
+ String jaasCtx = null;
+ try {
+ jaasCtx = Realm.getInstance(realm).getJAASContext();
+ } catch(Exception ex) {
+ if( ex instanceof LoginException )
+ throw (LoginException)ex;
+ else
+ throw (LoginException)new LoginException(ex.toString()).initCause(ex);
+ }
+
+ assert user != null;
+ assert pwd != null;
+ assert realm != null;
+ assert jaasCtx != null;
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("Logging in user [" + user + "] into realm: " +
+ realm + " using JAAS module: "+jaasCtx);
+ }
+
+ try {
+ // A dummyCallback is used to satisfy JAAS but it is never used.
+ // name/pwd info is already contained in Subject's Credential
+ LoginContext lg = new LoginContext(jaasCtx, s, dummyCallback);
+ lg.login();
+
+ } catch (Exception e) {
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINEST, "doPasswordLogin fails", e);
+ }
+ if(getAuditManager() != null && getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, false);
+ }
+ if( e instanceof LoginException )
+ throw (LoginException)e;
+ else
+ throw (LoginException)
+ new LoginException("Login failed: " + e.getMessage()).initCause(e);
+ }
+ if(getAuditManager() != null && getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, true);
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("Password login succeeded for : " + user);
+ }
+
+ setSecurityContext(user, s, realm);
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "Set security context as user: "+user);
+ }
+ }
+
+ /** Performs login for JMAC security. The difference between this
+ * method and others is that it just verifies whether the login will succeed
+ * in the given realm.
+ * It does not set the result of the authentication in the appserver runtime
+ * environment
+ * A silent return from this method means that the given user succeeding in
+ * authenticating with the given password in the given realm
+ * @param subject
+ * @param username
+ * @param password
+ * @param realmName the realm to authenticate under
+ * @returns Subject on successful authentication
+ * @throws LoginException
+ */
+ public static Subject jmacLogin(Subject subject,
+ String username, char[] password, String realmName)
+ throws LoginException {
+
+ if(realmName == null || !(Realm.isValidRealm(realmName))){
+ realmName = Realm.getDefaultRealm();
+ }
+ if (subject == null) {
+ subject = new Subject();
+ }
+ final Subject fs = subject;
+ final PasswordCredential pc =
+ new PasswordCredential(username, password, realmName);
+
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ fs.getPrivateCredentials().add(pc);
+ return fs;
+ }
+ });
+
+ String jaasCtx = null;
+ try {
+ jaasCtx = Realm.getInstance(realmName).getJAASContext();
+ } catch(Exception ex) {
+ if( ex instanceof LoginException )
+ throw (LoginException)ex;
+ else
+ throw (LoginException)
+ new LoginException(ex.toString()).initCause(ex);
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("jmac login user [" + username + "] into realm: " +
+ realmName + " using JAAS module: "+jaasCtx);
+ }
+
+ try{
+ // A dummyCallback is used to satisfy JAAS but it is never used.
+ // name/pwd info is already contained in Subject's Credential
+ LoginContext lg = new LoginContext(jaasCtx, fs, dummyCallback);
+ lg.login();
+ } catch (Exception e) {
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.auditAtnRefusedError,
+ username);
+ }
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(username, realmName, false);
+ }
+
+ if( e instanceof LoginException )
+ throw (LoginException)e;
+ else
+ throw (LoginException)
+ new LoginException("Login failed: " + e.getMessage()).initCause(e);
+ }
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(username, realmName, true);
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("jmac Password login succeeded for : " + username);
+ }
+
+ return subject;
+ // do not set the security Context
+ }
+
+ public static Subject jmacLogin(Subject subject,
+ X500Principal x500Principal) throws LoginException {
+
+ if (subject == null) {
+ subject = new Subject();
+ }
+
+ final Subject fs = subject;
+
+ String userName = "";
+ try {
+ final X500Name x500Name = new X500Name(
+ x500Principal.getName(X500Principal.RFC1779));
+ userName = x500Name.toString();
+
+ AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ fs.getPublicCredentials().add(x500Name);
+ return fs;
+ }
+ });
+
+ Realm realm = Realm.getInstance(CertificateRealm.AUTH_TYPE);
+ CertificateRealm certRealm = (CertificateRealm)realm;
+ String jaasCtx = certRealm.getJAASContext();
+ if (jaasCtx != null) {
+ // The subject has the Cretificate Credential.
+ LoginContext lg = new LoginContext(jaasCtx, fs, dummyCallback);
+ lg.login();
+ }
+ certRealm.authenticate(fs, x500Name);
+ } catch(Exception ex) {
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.auditAtnRefusedError,
+ userName);
+ }
+ if (getAuditManager().isAuditOn()){
+ getAuditManager().authentication(userName,
+ CertificateRealm.AUTH_TYPE, false);
+ }
+ if (ex instanceof LoginException) {
+ throw (LoginException)ex;
+ } else {
+ throw (LoginException)
+ new LoginException(ex.toString()).initCause(ex);
+ }
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("jmac cert login succeeded for: " + userName);
+ }
+
+ if (getAuditManager().isAuditOn()){
+ getAuditManager().authentication(userName,
+ CertificateRealm.AUTH_TYPE, true);
+ }
+ // do not set the security Context
+
+ return subject;
+ }
+
+ public static Subject jmacLogin(Subject subject, String identityAssertion, String realm) throws LoginException {
+
+ if (subject == null) {
+ subject = new Subject();
+ }
+ final Subject fs = subject;
+ String userName = identityAssertion;
+
+ try {
+ if (realm == null || "".equals(realm)) {
+ realm = Realm.getDefaultRealm();
+ }
+ Realm realmInst = Realm.getInstance(realm);
+ final Enumeration groups = realmInst.getGroupNames(userName);
+ if (groups != null && groups.hasMoreElements()) {
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+
+ public java.lang.Object run() {
+ while (groups.hasMoreElements()) {
+ String grp = (String) groups.nextElement();
+ fs.getPrincipals().add(new Group(grp));
+ }
+ return fs;
+ }
+ });
+ }
+ } catch (Exception ex) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "Exception when trying to populate groups for CallerPrincipal " + identityAssertion, ex);
+ }
+ }
+ return subject;
+ }
+
+ /**
+ * A special case login for handling X509CertificateCredential.
+ * This does not get triggered based on current RI code. See X500Login.
+ *
+ */
+ private static void doCertificateLogin(Subject s)
+ throws LoginException
+ {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "Processing X509 certificate login.");
+ }
+ String realm = CertificateRealm.AUTH_TYPE;
+ String user = null;
+ try{
+ Object obj = getPublicCredentials(s, X509CertificateCredential.class);
+
+ X509CertificateCredential xp = (X509CertificateCredential) obj;
+ user = xp.getAlias();
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Set security context as user: "+user);
+ }
+ setSecurityContext(user, s, realm);
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, true);
+ }
+ } catch(LoginException le){
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, false);
+ }
+ throw le;
+ }
+ }
+
+
+ /**
+ * A special case login for anonymous credentials (no login info).
+ *
+ */
+ private static void doAnonLogin()
+ throws LoginException
+ {
+ // instance of anononymous credential login with guest
+ SecurityContext.setUnauthenticatedContext();
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Set anonymous security context.");
+ }
+ }
+
+
+ /**
+ * A special case login for GSSUPName credentials.
+ *
+ */
+ private static void doGSSUPLogin(Subject s)
+ throws LoginException
+ {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.fine("Processing GSSUP login.");
+ }
+ String user = null;
+ String realm = Realm.getDefaultRealm();
+ try{
+ Object obj = getPublicCredentials(s, GSSUPName.class);
+
+ user = ((GSSUPName)obj).getUser();
+
+ setSecurityContext(user, s, realm);
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, true);
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("GSSUP login succeeded for : " + user);
+ }
+ } catch (LoginException le){
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm, false);
+ }
+ throw le;
+ }
+ }
+
+
+ /**
+ * A special case login for X500Name credentials.
+ * This is invoked for certificate login because the containers
+ * extract the X.500 name from the X.509 certificate before calling
+ * into this class.
+ *
+ */
+ public static void doX500Login(Subject s, String appModuleID)
+ throws LoginException
+ {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.fine("Processing X.500 name login.");
+ }
+ String user = null;
+ String realm_name = null;
+ try{
+ X500Name x500name = (X500Name)getPublicCredentials(s, X500Name.class);
+ user = x500name.getName();
+
+ // In the RI-inherited implementation this directly creates
+ // some credentials and sets the security context. This means
+ // that the certificate realm does not get an opportunity to
+ // process the request. While the realm will not do any
+ // authentication (already done by this point) it can choose
+ // to adjust the groups or principal name or other variables
+ // of the security context. Of course, bug 4646134 needs to be
+ // kept in mind at all times.
+
+ Realm realm = Realm.getInstance(CertificateRealm.AUTH_TYPE);
+
+ if (realm instanceof CertificateRealm) { // should always be true
+
+ CertificateRealm certRealm = (CertificateRealm)realm;
+ String jaasCtx = certRealm.getJAASContext();
+ if (jaasCtx != null) {
+ // The subject has the Cretificate Credential.
+ LoginContext lg = new LoginContext(jaasCtx, s, new ServerLoginCallbackHandler(user, null, appModuleID));
+ lg.login();
+ }
+ certRealm.authenticate(s, x500name);
+ realm_name = CertificateRealm.AUTH_TYPE;
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm_name, true);
+ }
+ } else {
+ _logger.warning(SecurityLoggerInfo.certLoginBadRealmError);
+ realm_name = realm.getName();
+ setSecurityContext(user, s, realm_name);
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("X.500 name login succeeded for : " + user);
+ }
+ } catch (LoginException le){
+ if(getAuditManager().isAuditOn()){
+ getAuditManager().authentication(user, realm_name, false);
+ }
+ throw le;
+ } catch (Exception ex) {
+ throw (LoginException)new LoginException(ex.toString()).initCause(ex);
+ }
+ }
+
+
+ /**
+ * Retrieve a public credential of the given type (java class) from the
+ * subject.
+ *
+ * <P>This method retains the RI assumption that only the first
+ * credential of the given type is used.
+ *
+ */
+ private static Object getPublicCredentials(Subject s, Class<?> cls)
+ throws LoginException
+ {
+ Set credset = s.getPublicCredentials(cls);
+
+ final Iterator iter = credset.iterator();
+
+ if(!iter.hasNext()) {
+ String credmsg = cls.toString();
+ if(_logger.isLoggable(Level.FINER)){
+ _logger.finer("Expected public credentials of type : " +
+ credmsg + " but none found.");
+ }
+ throw new LoginException("Expected public credential of type: "+
+ credmsg + " but none found.");
+ }
+
+ Object obj = null;
+ try{
+ obj = AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ return iter.next();
+ }
+ });
+ } catch (Exception e){
+ // should never come here
+ if( e instanceof LoginException )
+ throw (LoginException)e;
+ else
+ throw (LoginException)
+ new LoginException("Failed to retrieve public credential: "+
+ e.getMessage()).initCause(e);
+ }
+
+ return obj;
+ }
+
+
+ /**
+ * Retrieve a private credential of the given type (java class) from the
+ * subject.
+ *
+ * <P>This method retains the RI assumption that only the first
+ * credential of the given type is used.
+ *
+ */
+ private static Object getPrivateCredentials(Subject subject,
+ Class<?> cls)
+ throws LoginException
+ {
+ final Subject s = subject;
+ final Class<?> cl = cls;
+
+ final Set credset = (Set)
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ return
+ s.getPrivateCredentials(cl);
+ }
+ });
+
+ final Iterator iter = credset.iterator();
+
+ if (!iter.hasNext()) {
+ String credmsg = cls.toString();
+ if(_logger.isLoggable(Level.FINER)){
+ _logger.finer("Expected private credential of type: "+
+ credmsg + " but none found.");
+ }
+ throw new LoginException("Expected private credential of type: "+
+ credmsg + " but none found.");
+ }
+
+ // retrieve only first credential of give type
+ Object obj = null;
+ try{
+ obj = AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ return iter.next();
+ }
+ });
+ } catch (Exception e){
+ // should never come here
+ if( e instanceof LoginException )
+ throw (LoginException)e;
+ else
+ throw (LoginException)
+ new LoginException("Failed to retrieve private credential: "+
+ e.getMessage()).initCause(e);
+ }
+
+ return obj;
+ }
+
+
+ /**
+ * This method sets the security context on the current Thread Local
+ * Storage
+ * @param String username is the user who authenticated
+ * @param Subject is the subject representation of the user
+ * @param Credentials the credentials that the server associated with it
+ */
+private static void setSecurityContext(String userName,
+ Subject subject, String realm) {
+
+ SecurityContext securityContext = new SecurityContext(userName, subject, realm);
+ SecurityContext.setCurrent(securityContext);
+ }
+
+ /**
+ * Set the current security context on the Thread Local Storage to null.
+ *
+ */
+ private static void unsetSecurityContext() {
+ SecurityContext.setCurrent((SecurityContext)null);
+ }
+ /**
+ * Perform login on the client side.
+ * It just simulates the login on the client side.
+ * The method uses the callback handlers and generates correct
+ * credential information that will be later sent to the server
+ * @param int type whether it is <i> username_password</i> or
+ * <i> certificate </i> based login.
+ * @param CallbackHandler the callback handler to gather user information.
+ * @exception LoginException the exception thrown by the callback handler.
+ */
+ public static Subject doClientLogin(int type,
+ javax.security.auth.callback.CallbackHandler jaasHandler)
+ throws LoginException
+ {
+ final javax.security.auth.callback.CallbackHandler handler =
+ jaasHandler;
+ // the subject will actually be filled in with a PasswordCredential
+ // required by the csiv2 layer in the LoginModule.
+ // we create the dummy credential here and call the
+ // set security context. Thus, we have 2 credentials, one each for
+ // the csiv2 layer and the other for the RI.
+ final Subject subject = new Subject();
+
+ if (type == SecurityConstants.USERNAME_PASSWORD ){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ lg.login();
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ postClientAuth(subject, PasswordCredential.class);
+ return subject;
+ } else if (type == SecurityConstants.CERTIFICATE){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_CERTIFICATE,
+ subject, handler);
+ lg.login();
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ postClientAuth(subject, X509CertificateCredential.class);
+ return subject;
+ } else if (type == SecurityConstants.ALL){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lgup =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ LoginContext lgc =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_CERTIFICATE,
+ subject, handler);
+ lgup.login();
+ postClientAuth(subject, PasswordCredential.class);
+
+ lgc.login();
+ postClientAuth(subject,
+ X509CertificateCredential.class);
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ return subject;
+ } else{
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ lg.login();
+ postClientAuth(subject, PasswordCredential.class);
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+ return null;
+ }
+ });
+ return subject;
+ }
+ }
+
+ /**
+ * Perform logout on the client side.
+ * @exception LoginException
+ */
+ public static void doClientLogout() throws LoginException {
+ unsetClientSecurityContext();
+ }
+ /**
+ * Performs Digest authentication based on RFC 2617. It
+ *
+ * @param digestCred DigestCredentials
+ */
+ public static void login(DigestCredentials digestCred) throws javax.security.auth.login.LoginException {
+ Subject subject = new Subject();
+ subject.getPrivateCredentials().add(digestCred);
+ String jaasCtx = null;
+ try {
+ jaasCtx = Realm.getInstance(digestCred.getRealmName()).getJAASContext();
+ } catch (Exception ex) {
+ if (ex instanceof LoginException) {
+ throw (LoginException) ex;
+ } else {
+ throw (LoginException) new LoginException(ex.toString()).initCause(ex);
+ }
+ }
+
+ try {
+ // A dummyCallback is used to satisfy JAAS but it is never used.
+ // name/pwd info is already contained in Subject's Credential
+ LoginContext lg = new LoginContext(jaasCtx, subject, dummyCallback);
+ lg.login();
+ } catch (Exception e) {
+ if (_logger.isLoggable(Level.INFO)) {
+ _logger.log(Level.INFO, SecurityLoggerInfo.auditAtnRefusedError, digestCred.getUserName());
+ }
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINEST, "doPasswordLogin fails", e);
+ }
+ if (getAuditManager().isAuditOn()) {
+ getAuditManager().authentication(digestCred.getUserName(), digestCred.getRealmName(), false);
+ }
+ if (e instanceof LoginException) {
+ throw (LoginException) e;
+ } else {
+ throw (LoginException) new LoginException("Login failed: " + e.getMessage()).initCause(e);
+ }
+ }
+
+ setSecurityContext(digestCred.getUserName(), subject, digestCred.getRealmName());
+ }
+
+
+ /**
+ * Extract the relevant username and realm information from the
+ * subject and sets the correct state in the security context. The
+ * relevant information is set into the Thread Local Storage from
+ * which then is extracted to send over the wire.
+ *
+ * @param Subject the subject returned by the JAAS login.
+ * @param Class the class of the credential object stored in the subject
+ *
+ */
+ private static void postClientAuth(Subject subject, Class<?> clazz){
+ final Class<?> clas = clazz;
+ final Subject fs = subject;
+ Set credset =
+ (Set) AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ if(_logger.isLoggable(Level.FINEST)){
+ _logger.log(Level.FINEST,"LCD post login subject :" + fs);
+ }
+ return fs.getPrivateCredentials(clas);
+ }
+ });
+ final Iterator iter = credset.iterator();
+ while(iter.hasNext()) {
+ Object obj = null;
+ try{
+ obj = AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ return iter.next();
+ }
+ });
+ } catch (Exception e){
+ // should never come here
+ _logger.log(Level.SEVERE,
+ SecurityLoggerInfo.securityAccessControllerActionError,
+ e);
+ }
+ if(obj instanceof PasswordCredential) {
+ PasswordCredential p = (PasswordCredential) obj;
+ String user = p.getUser();
+ if(_logger.isLoggable(Level.FINEST)){
+ String realm = p.getRealm();
+ _logger.log(Level.FINEST,"In LCD user-pass login:" +
+ user +" realm :" + realm);
+ }
+ setClientSecurityContext(user, fs);
+ return;
+ } else if (obj instanceof X509CertificateCredential){
+ X509CertificateCredential p = (X509CertificateCredential) obj;
+ String user = p.getAlias();
+ if(_logger.isLoggable(Level.FINEST)){
+ String realm = p.getRealm();
+ _logger.log(Level.FINEST,"In LCD cert-login::" +
+ user +" realm :" + realm);
+ }
+ setClientSecurityContext(user, fs);
+ return;
+ }
+ }
+ }
+
+
+ /**
+ * Sets the security context on the appclient side.
+ * It sets the relevant information into the TLS
+ * @param String username is the user who authenticated
+ * @param Subject is the subject representation of the user
+ * @param Credentials the credentials that the server associated with it
+ */
+ private static void setClientSecurityContext(String username,
+ Subject subject) {
+ ClientSecurityContext securityContext =
+ new ClientSecurityContext(username, subject);
+ ClientSecurityContext.setCurrent(securityContext);
+ }
+
+
+ /**
+ * Unsets the current appclient security context on the Thread
+ * Local Storage
+ */
+ private static void unsetClientSecurityContext() {
+ ClientSecurityContext.setCurrent(null);
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/PasswordLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/PasswordLoginModule.java
new file mode 100644
index 0000000..69fccdc
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/PasswordLoginModule.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import com.sun.enterprise.security.BasePasswordLoginModule;
+import com.sun.enterprise.security.auth.realm.Realm;
+import javax.security.auth.login.LoginException;
+
+/**
+ * Abstract base class for password-based login modules.
+ * This class is provided for
+ * backward compatibility and is a candidate for deprecation.
+ *
+ */
+@Deprecated
+public abstract class PasswordLoginModule extends BasePasswordLoginModule
+{
+
+ /**
+ * Maintain RI compatibility.
+ *
+ * <P>This is a convenience method which can be used by subclasses
+ * to complete the steps required by RI legacy authentication code.
+ * Most of this should go away if a clean JAAS/Subject based
+ * infrastructure is provided. But for now this must be done.
+ *
+ * <P>Note that this method is called after the authentication
+ * has succeeded. If authentication failed do not call this method.
+ *
+ * <P>A lot of the RI behavior is still present here. Some of the
+ * most notable points to remember:
+ * <ul>
+ * <li>Global instance field succeeded is set to true by this method.
+ *
+ * @param username Name of authenticated user.
+ * @param password Password of this user.
+ * @param theRealm Current Realm object for this authentication.
+ * @param groups String array of group memberships for user (could be
+ * empty).
+ * @returns void
+ *
+ */
+ @Deprecated
+ public final void commitAuthentication(String username,
+ String password,
+ Realm theRealm,
+ String[] groups)
+ {
+ commitUserAuthentication(groups);
+ }
+
+ /**
+ * Since the passwords are to be stored as to have char[]
+ * BT: 6946553.
+ * Retaining the other method for backward compatability
+ *
+ * @param username Name of authenticated user.
+ * @param password Password of this user in char[].
+ * @param theRealm Current Realm object for this authentication.
+ * @param groups String array of group memberships for user (could be
+ * empty).
+ * @returns void
+ *
+ */
+ public final void commitAuthentication(String username,
+ char[] password,
+ Realm theRealm,
+ String[] groups)
+ {
+ commitUserAuthentication(groups);
+ }
+ /**
+ * Older implementations can implement authenticate. While new implementation
+ * calls authenticateUser
+ * @throws LoginException
+ */
+ protected final void authenticateUser () throws LoginException{
+ authenticate();
+ }
+
+ /**
+ * Perform authentication decision.
+ * Method returns silently on success and returns a LoginException
+ * on failure.
+ * To be implmented by sub-classes
+ * @return void authenticate returns silently on successful authentication.
+ * @throws com.sun.enterprise.security.LoginException on authentication failure.
+ *
+ */
+ abstract protected void authenticate()
+ throws LoginException;
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/SolarisLoginModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/SolarisLoginModule.java
new file mode 100644
index 0000000..1ef9cc6
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/SolarisLoginModule.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login;
+
+import java.util.*;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+
+import javax.security.auth.*;
+import javax.security.auth.callback.*;
+import javax.security.auth.login.*;
+import javax.security.auth.spi.*;
+
+import com.sun.enterprise.security.auth.realm.solaris.SolarisRealm;
+
+// limit RI imports
+import com.sun.enterprise.security.auth.Privilege;
+import com.sun.enterprise.security.auth.PrivilegeImpl;
+
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import javax.security.auth.login.LoginException;
+
+/**
+ * Solaris realm login module.
+ *
+ * <P>Processing is delegated to the SolarisRealm class which accesses
+ * the native methods.
+ *
+ * @see com.sun.enterprise.security.auth.login.PasswordLoginModule
+ * @see com.sun.enterprise.security.auth.realm.solaris.SolarisRealm
+ *
+ */
+public class SolarisLoginModule extends PasswordLoginModule
+{
+
+ /**
+ * Perform solaris authentication. Delegates to SolarisRealm.
+ *
+ * @throws LoginException If login fails (JAAS login() behavior).
+ *
+ */
+ protected void authenticate()
+ throws LoginException
+ {
+ if (!(_currentRealm instanceof SolarisRealm)) {
+ String msg = sm.getString("solarislm.badrealm");
+ throw new LoginException(msg);
+ }
+
+ SolarisRealm solarisRealm = (SolarisRealm)_currentRealm;
+
+ // A solaris user must have a name not null so check here.
+ if ( (_username == null) || (_username.length() == 0) ) {
+ String msg = sm.getString("solarislm.nulluser");
+ throw new LoginException(msg);
+ }
+
+ String[] grpList = solarisRealm.authenticate(_username, getPasswordChar());
+
+ if (grpList == null) { // JAAS behavior
+ String msg = sm.getString("solarislm.loginfail", _username);
+ throw new LoginException(msg);
+ }
+
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.finest("Solaris login succeeded for: " + _username);
+ }
+
+ commitAuthentication(_username, getPasswordChar(),
+ _currentRealm, grpList);
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LocalStrings.properties
new file mode 100644
index 0000000..5bcf3a2
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LocalStrings.properties
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+enterprise.security.login_failed=Login Failed.
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LoginException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LoginException.java
new file mode 100644
index 0000000..23dd42e
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/LoginException.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login.common;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+/**
+ * LoginException is thrown by the LoginContext class whenever
+ * the following happens: <UL>
+ * <LI> If the client is unable to authenticate successfully with the
+ * </UL>
+ * @see com.sun.enterprise.security.auth.AuthenticationStatus
+ * @author Harish Prabandham
+ * @author Harpreet Singh
+ */
+
+public class LoginException extends SecurityException {
+
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(LoginException.class);
+
+ private boolean status = false;
+
+
+ /**
+ * Create a new LoginException object with the given message
+ * @param The message indicating why authentication failed.
+ */
+ public LoginException(String message) {
+ super(message);
+ }
+
+
+ /**
+ * Create a new LoginException object with the given authentication
+ * value.
+ * @param The AuthenticationStatus object
+ */
+ public LoginException(boolean as){
+ super(localStrings.getLocalString("enterprise.security.login_failed",
+ "Login Failed."));
+ status = as;
+ }
+
+
+ /**
+ * Returns the status of the Authentication.
+ */
+ public boolean getStatus(){
+ return status;
+ }
+
+}
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/PasswordCredential.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/PasswordCredential.java
new file mode 100644
index 0000000..d220a37
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/PasswordCredential.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login.common;
+
+import java.util.Arrays;
+
+/**
+ * This class holds the user password for the shared password realm and the
+ * realm name. This credential is added as a private credential to the
+ * JAAS subject.
+ */
+
+public class PasswordCredential {
+ private String username;
+ // private String password;
+ private char[] password;
+ private String realm;
+ private boolean readOnly = false;
+ // target_name is filled in by the SecSecurityServer interceptor
+ // only when a CSIv2 GSSUP authenticator is received.
+
+ private byte[] target_name = {};
+
+ /**
+ * Construct a credential with the specified password and realm name.
+ * @param the password.
+ * @param the realm name. The only value supported for now is "default".
+ */
+ public PasswordCredential(String user, char[] password, String realm)
+ {
+ this.username = user;
+ //Copy the password to another reference before storing it to the
+ //instance field.
+ char[] passwordCopy = (password == null) ? null : Arrays.copyOf(password, password.length);
+ this.password = passwordCopy;
+ this.realm = realm;
+
+ if (this.username == null ) { this.username = ""; }
+ if (this.password == null ) { this.password = new char[]{}; }
+ if (this.realm == null ) { this.realm = ""; }
+ }
+
+
+ /**
+ * called by SecServerRequestInterceptor
+ * The object if created on the server side is readonly
+ */
+ public PasswordCredential(String user, char[] password,
+ String realm, byte[] target_name)
+ {
+ this(user, password, realm);
+ this.target_name = target_name;
+ readOnly = true;
+ }
+
+
+ /**
+ * Return the realm name.
+ * @return the realm name. Only value supported for now is "default".
+ */
+ public String getRealm() {
+ return realm;
+ }
+
+
+ /**
+ * Return the username.
+ * @return the user name.
+ */
+ public String getUser() {
+ return username;
+ }
+
+ public void setRealm(String realm){
+ if(!readOnly){
+ this.realm = realm;
+ }
+ }
+
+ /**
+ * Return the password.
+ * @return the password.
+ */
+ public char[] getPassword() {
+ //Copy the password to another reference before returning it
+ char[] passwordCopy = (password == null) ? null : Arrays.copyOf(password, password.length);
+ return passwordCopy;
+ }
+
+
+ /**
+ * Return the target_name
+ * @return the target_name
+ */
+ public byte[] getTargetName() {
+ return this.target_name;
+ }
+
+ /**
+ * Compare two instances of the credential and return true if they are
+ * the same and false otherwise.
+ * @param the object that this instance is being compared to.
+ * @return true if the instances are equal, false otherwise
+ */
+ public boolean equals(Object o) {
+ if(o instanceof PasswordCredential) {
+ PasswordCredential pc = (PasswordCredential) o;
+ if(pc.getUser().equals(username) &&
+ Arrays.equals(pc.getPassword(),password) &&
+ pc.getRealm().equals(realm)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Return the hashCode computed from the password and realm name.
+ * @return the hash code.
+ */
+ public int hashCode() {
+ return username.hashCode() + Arrays.hashCode(password) + realm.hashCode();
+ }
+
+
+ /**
+ * The string representation of the credential.
+ */
+ public String toString() {
+ String s = "Realm=" + realm;
+ s = s + " Username=" + username;
+ s = s + " Password=" + "########";
+ s = s + " TargetName = " + new String(target_name);
+ return s;
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/ServerLoginCallbackHandler.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/ServerLoginCallbackHandler.java
new file mode 100644
index 0000000..524cee9
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/ServerLoginCallbackHandler.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login.common;
+
+import com.sun.enterprise.security.auth.realm.certificate.CertificateRealm;
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import javax.security.auth.callback.*;
+
+
+/**
+ * This is the default callback handler provided by the application
+ * client container. The container tries to use the application specified
+ * callback handler (if provided). If there is no callback handler or if
+ * the handler cannot be instantiated then this default handler is used.
+ */
+public class ServerLoginCallbackHandler implements CallbackHandler
+{
+ private static final String GP_CB="javax.security.auth.message.callback.GroupPrincipalCallback";
+ private static final String GPCBH_UTIL = "com.sun.enterprise.security.jmac.callback.ServerLoginCBHUtil";
+ private static final String GPCBH_UTIL_METHOD="processGroupPrincipal";
+ private String username = null;
+ private char[] password = null;
+ private String moduleID = null;
+
+ public ServerLoginCallbackHandler(String username, char[] password) {
+ this.username = username;
+ this.password = password;
+ }
+
+ public ServerLoginCallbackHandler(String username, char[] password, String moduleID) {
+ this.username = username;
+ this.password = password;
+ this.moduleID = moduleID;
+ }
+
+ public ServerLoginCallbackHandler(){
+ }
+
+ public void setUsername(String user){
+ username = user;
+ }
+
+ public void setPassword(char[] pass){
+ password = pass;
+ }
+
+ public void setModuleID(String moduleID) {
+ this.moduleID = moduleID;
+ }
+
+
+ /**
+ * This is the callback method called when authentication data is
+ * required. It either pops up a dialog box to request authentication
+ * data or use text input.
+ * @param the callback object instances supported by the login module.
+ */
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback){
+ NameCallback nme = (NameCallback)callbacks[i];
+ nme.setName(username);
+ } else if (callbacks[i] instanceof PasswordCallback){
+ PasswordCallback pswd = (PasswordCallback)callbacks[i];
+ pswd.setPassword(password);
+ } else if (callbacks[i] instanceof CertificateRealm.AppContextCallback){
+ ((CertificateRealm.AppContextCallback) callbacks[i]).setModuleID(moduleID);
+ } else if (GP_CB.equals(callbacks[i].getClass().getName())){
+ processGroupPrincipal(callbacks[i]);
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+ }
+
+ private static void processGroupPrincipal(Callback callback) throws UnsupportedCallbackException {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ try {
+ Class clazz = loader.loadClass(GPCBH_UTIL);
+ Method meth = clazz.getMethod(GPCBH_UTIL_METHOD, Callback.class);
+ meth.invoke(null, callback);
+ } catch (IllegalAccessException ex) {
+ throw new UnsupportedCallbackException(callback);
+ } catch (IllegalArgumentException ex) {
+ throw new UnsupportedCallbackException(callback);
+ } catch (InvocationTargetException ex) {
+ throw new UnsupportedCallbackException(callback);
+ } catch (NoSuchMethodException ex) {
+ throw new UnsupportedCallbackException(callback);
+ } catch (SecurityException ex) {
+ throw new UnsupportedCallbackException(callback);
+ } catch (ClassNotFoundException ex) {
+ throw new UnsupportedCallbackException(callback);
+ }
+
+ }
+
+
+}
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/X509CertificateCredential.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/X509CertificateCredential.java
new file mode 100644
index 0000000..5bdc209
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/login/common/X509CertificateCredential.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.login.common;
+
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+
+/**
+ * This class holds the user certificate for the certificate realm and the
+ * realm name. This credential is added as a public credential to the
+ * JAAS subject.
+ */
+
+public class X509CertificateCredential {
+ private X509Certificate[] certChain;
+ private String realm;
+ private String alias;
+
+ /**
+ * Construct a credential with the specified X509Certificate certificate
+ * chain, realm name and alias.
+ * @param the X509Certificate.
+ * @param the alias for the certificate
+ * @param the realm name. The only value supported for now is "certificate".
+ */
+
+ public X509CertificateCredential(X509Certificate[] certChain,
+ String alias, String realm)
+ {
+ this.certChain = certChain;
+ this.alias = alias;
+ this.realm = realm;
+ }
+
+ /**
+ * Return the alias for the certificate.
+ * @return the alias.
+ */
+ public String getAlias() {
+ return alias;
+ }
+
+ /**
+ * Return the realm name.
+ * @return the realm name. Only value supported for now is "certificate".
+ */
+ public String getRealm() {
+ return realm;
+ }
+
+ /**
+ * Return the chain of certificates.
+ * @return the chain of X509Certificates.
+ */
+ public X509Certificate[] getX509CertificateChain() {
+ return certChain;
+ }
+
+ /**
+ * Compare two instances of the credential and return true if they are
+ * the same and false otherwise.
+ * @return true if the instances are equal, false otherwise.
+ */
+ public boolean equals(Object o) {
+ if(o instanceof X509CertificateCredential) {
+ X509CertificateCredential pc = (X509CertificateCredential) o;
+ if(pc.getRealm().equals(realm) && pc.getAlias().equals(alias)) {
+ X509Certificate[] certs = pc.getX509CertificateChain();
+ for(int i = 0; i < certs.length; i++) {
+ if(!certs[i].equals(certChain[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return the hashCode computed from the certificate, realm and alias.
+ * @return the hash code.
+ */
+ public int hashCode() {
+ return Arrays.hashCode(certChain) + realm.hashCode() + ((alias != null)?alias.hashCode():0);
+ }
+
+ /**
+ * String representation of the credential.
+ */
+ public String toString() {
+ String s = "Realm=" + realm;
+ s = s + " alias=" + alias;
+ StringBuffer certChainStr = new StringBuffer("");
+ for (int i=0; i < certChain.length; i++) {
+ certChainStr.append(certChain[i].toString());
+ certChainStr.append("\n");
+ }
+ s = s + " X509Certificate=" + certChainStr.toString();
+ return s;
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/nonce/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/nonce/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/nonce/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/AuthenticationHandler.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/AuthenticationHandler.java
new file mode 100644
index 0000000..bf3513a
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/AuthenticationHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import java.security.Principal;
+import com.sun.enterprise.security.auth.*;
+
+/**
+ * This interface is used by the Authentication Service to have the
+ * Principal authenticated by the realm. A realm provides an
+ * implementation of this interface.
+ * @author Harish Prabandham
+ * @author Harpreet Singh
+ */
+public interface AuthenticationHandler {
+ /**
+ * Returns the Realm that this Authentication Handler is authenticating
+ * in.
+ * @return The Realm object in which this handler is authenticating in.
+ */
+ public Realm getRealm();
+
+ /**
+ * This method authenticates the given principal using the specified
+ * authentication data and the Principal's Credentials. The result of
+ * the authentication is returned back.
+ * @param The principal (user) being authenticated.
+ * @param The data needed for authentication.
+ * @return boolean denoting true for success and false for failure
+ * authentication.
+ */
+ public boolean doAuthentication(String principalName,
+ byte[] authData);
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadRealmException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadRealmException.java
new file mode 100644
index 0000000..cf68d5d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadRealmException.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when a Realm is found to be corrupted for some reason.
+ * This usually reflects some sort of problem with data structures such
+ * as those holding information about users, groups, or ACLs.
+ *
+ * @author Harish Prabandham
+ */
+public class BadRealmException extends Exception
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the problem with the realm
+ */
+ public BadRealmException (String info) { super (info); }
+
+ public BadRealmException() {
+ super();
+ }
+
+ public BadRealmException(Throwable cause) {
+ super(cause);
+ }
+
+ public BadRealmException(String info, Throwable cause) {
+ super(info, cause);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadUserException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadUserException.java
new file mode 100644
index 0000000..5f2c55d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/BadUserException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when a User is found to be corrupted for some reason.
+ * This is a special case of a realm data structure being corrupted.
+ *
+ * @author Harish Prabandham
+ */
+public class BadUserException extends BadRealmException
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the problem with the user
+ */
+ public BadUserException (String info) { super (info); }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupMapper.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupMapper.java
new file mode 100644
index 0000000..3961bf0
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupMapper.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ *
+ * @author Kumar
+ */
+public class GroupMapper {
+
+ private Map<String, ArrayList<String>> groupMappingTable = new HashMap<String, ArrayList<String>>();
+
+ public void parse(String mappingStr) {
+ StringTokenizer tokenizer = new StringTokenizer(mappingStr, ";");
+ while(tokenizer.hasMoreElements()) {
+ String mapping = tokenizer.nextToken();
+ String[] mappingGroups = mapping.split(",");
+ String mappedGroup = null;
+ int indexOfArrow = mapping.indexOf("->");
+ if (indexOfArrow > 0 && mappingGroups != null && (mappingGroups.length > 0)) {
+ String tmpGroup = mapping.substring(indexOfArrow + 2);
+ mappedGroup = tmpGroup.trim();
+ }
+ validate(mappedGroup, mappingGroups);
+ for (String grp : mappingGroups) {
+ int aIndex = grp.indexOf("->");
+ String theGroup = null;
+ if (aIndex > 0) {
+ String tGrp = grp.substring(0, aIndex);
+ theGroup = tGrp.trim();
+ } else {
+ theGroup = grp.trim();
+ }
+ ArrayList<String> mappedGroupList = groupMappingTable.get(theGroup);
+ if (mappedGroupList == null) {
+ mappedGroupList = new ArrayList<String>();
+ }
+ mappedGroupList.add(mappedGroup);
+ groupMappingTable.put(theGroup, mappedGroupList);
+ }
+ }
+ }
+
+ public void getMappedGroups(String group, ArrayList<String> result) {
+ if (result == null) {
+ throw new RuntimeException("result argument cannot be NULL");
+ }
+ ArrayList<String> mappedGrps = groupMappingTable.get(group);
+ if (mappedGrps == null || mappedGrps.isEmpty()) {
+ return;
+ }
+ addUnique(result,mappedGrps);
+ //look for transitive closure
+ ArrayList<String> result1 = new ArrayList<String>();
+ for (String str : mappedGrps) {
+ getMappedGroups(group, str,result1);
+ }
+ addUnique(result, result1);
+ }
+
+ private void addUnique(ArrayList<String> dest, ArrayList<String> src) {
+ for (String str : src) {
+ if (!dest.contains(str)) {
+ dest.add(str);
+ }
+ }
+ }
+ /*
+ public void traverse() {
+ Iterator<String> it = groupMappingTable.keySet().iterator();
+ while(it.hasNext()) {
+ String key = it.next();
+ System.out.println();
+ System.out.print( key + "<<<Is Mapped to>>>");
+ ArrayList<String> list = new ArrayList<String>();
+ getMappedGroups(key, list);
+ if (list != null) {
+ for (String str : list) {
+ System.out.print(str + ", ");
+ }
+ }
+ System.out.println();
+ }
+ }*/
+ /**
+ * @param args the command line arguments
+
+ public static void main(String[] args) {
+ // TODO code application logic here
+ GroupMapper mapper = new GroupMapper();
+ mapper.parse(mappingStr);
+ mapper.traverse();
+ }*/
+
+ private void getMappedGroups(String group, String str, ArrayList<String> result) {
+
+ ArrayList<String> mappedGrps = groupMappingTable.get(str);
+ if (mappedGrps == null || mappedGrps.isEmpty()) {
+ return;
+ }
+ if (mappedGrps.contains(group)) {
+ throw new RuntimeException("Illegal Mapping: cycle detected with group'" + group);
+ }
+ addUnique(result,mappedGrps);
+ for (String str1 : mappedGrps) {
+ getMappedGroups(group, str1,result);
+ }
+ }
+
+ private void validate(String mappedGroup, String[] mappingGroups) {
+ for (String str : mappingGroups) {
+ int aIndex = str.indexOf("->");
+ String theGroup = null;
+ if (aIndex > 0) {
+ theGroup = str.substring(0, aIndex);
+ } else {
+ theGroup = str;
+ }
+ if (theGroup.equals(mappedGroup)) {
+ throw new RuntimeException("Illegal Mapping: Identity Mapping of group '" + theGroup + "' to '" + theGroup + "'");
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupNotEmptyException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupNotEmptyException.java
new file mode 100644
index 0000000..689863b
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/GroupNotEmptyException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when an operation is requested to remove a group that has
+ * a list of users.
+ *
+ * @author Harpreet Singh
+ */
+public class GroupNotEmptyException extends Exception
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the user which does not exist
+ */
+ public GroupNotEmptyException (String info) { super (info); }
+}
+
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/IASRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/IASRealm.java
new file mode 100644
index 0000000..c5e5133
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/IASRealm.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+import com.sun.enterprise.security.BaseRealm;
+
+
+/**
+ * Parent class for iAS Realm classes.
+ *
+ * This class no longer implements the methods of Realm, instead it extends
+ * from BaseRealm and now is only a place holder for migration and is a
+ * candidate for deprecation.
+ *
+ */
+public abstract class IASRealm extends BaseRealm
+{
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/InvalidOperationException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/InvalidOperationException.java
new file mode 100644
index 0000000..d3749b9
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/InvalidOperationException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when an operation is invoked on a realm that does not
+ * support it.
+ * e.g. Invoking getGroups (username) is not supported by a certificate realm.
+ * @author Harpreet Singh
+ */
+public class InvalidOperationException extends Exception
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the problem with the realm
+ */
+ public InvalidOperationException (String info) { super (info); }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/LocalStrings.properties
new file mode 100644
index 0000000..4a8d207
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/LocalStrings.properties
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+realm.already_exists=This Realm already exists.
+realm.no_such_realm=Realm {0} does not exists.
+## Missing required property {0} for {JDBCRealm}.
+realm.missingprop=Missing required property {0} for {1}.
+iasrealm.notsupported=Operation not supported.
+filerealm.nofile=Incomplete configuration in file realm: file not specified.
+filerealm.nomodule=Incomplete configuration in file realm: login module not specified.
+filerealm.nouser=No such user [{0}].
+filerealm.noaccess=Unable to create keyfile: {0}
+ldaprealm.badconfig=Incomplete configuration of ldap realm: url: {0} baseDN: {1} login module: {2}
+ldaprealm.badmode=Unsupported mode {0}.
+ldaprealm.usernotfound=User {0} not found.
+ldaprealm.bindfailed=LDAP bind failed for {0}.
+
+solarisrealm.nojaas=Solaris realm jaas-context not set.
+jdbcrealm.cantconnect=Unable to connect to datasource {0} for database user {1}.
+jdbcrealm.nodigestalg=Digest algorithm {0} is not supported.
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchRealmException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchRealmException.java
new file mode 100644
index 0000000..7498383
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchRealmException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when an operation is requested on a realm which
+ * does not exist.
+ *
+ * @author Harish Prabandham
+ */
+public class NoSuchRealmException extends Exception
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the realm which does not exist
+ */
+ public NoSuchRealmException (String info) { super (info); }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchUserException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchUserException.java
new file mode 100644
index 0000000..7ddfcab
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/NoSuchUserException.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+
+/**
+ * Exception thrown when an operation is requested on a user which
+ * does not exist.
+ *
+ * @author Harish Prabandham
+ */
+public class NoSuchUserException extends Exception
+{
+ /**
+ * Constructs the exception, with descriptive information.
+ *
+ * @param info describes the user which does not exist
+ */
+ public NoSuchUserException (String info) { super (info); }
+}
+
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/Realm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/Realm.java
new file mode 100644
index 0000000..a3446aa
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/Realm.java
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.util.IASSecurityException;
+import java.io.*;
+import java.util.*;
+import com.sun.enterprise.util.*;
+import java.lang.ref.WeakReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.external.probe.provider.PluginPoint;
+import org.glassfish.external.probe.provider.StatsProviderManager;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.api.ClassLoaderHierarchy;
+import org.glassfish.internal.api.Globals;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * javadoc
+ *
+ * @see java.security.Principal
+ *
+ * @author Harish Prabandham
+ * @author Harpreet Singh
+ * @author Jyri Virkki
+ * @author Shing Wai Chan
+ *
+ */
+@Contract
+public abstract class Realm implements Comparable {
+
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(Realm.class);
+
+// private static Hashtable loadedRealms = new Hashtable();
+ private String myName;
+
+ // Keep track of name of default realm. This is updated during startup
+ // using value from server.xml
+// private static String defaultRealmName="default";
+
+ // Keep a mapping from "default" to default realm (if no such named
+ // realm is present) for the sake of all the hardcoded accesses to it.
+ // This needs to be removed as part of RI security service cleanup.
+ final static String RI_DEFAULT="default";
+
+ // All realms have a set of properties from config file, consolidate.
+ private Properties ctxProps;
+
+ // for assign-groups
+ private static final String PARAM_GROUPS = "assign-groups";
+ private static final String GROUPS_SEP = ",";
+ private List<String> assignGroups = null;
+ public static final String PARAM_GROUP_MAPPING="group-mapping";
+ protected GroupMapper groupMapper = null;
+ private static RealmStatsProvider realmStatsProvier = null;
+ private static final String DEFAULT_DIGEST_ALGORITHM = "default-digest-algorithm";
+ private static final String DEFAULT_DEF_DIG_ALGO_VAL = "SHA-256";
+
+ private static WeakReference<RealmsManager> realmsManager = new WeakReference<RealmsManager>(null);
+ private String defaultDigestAlgorithm = null;
+
+ protected static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+
+ /**
+ * Returns the name of this realm.
+ *
+ * @return realm name.
+ */
+ public final String getName() {
+ return myName;
+ }
+
+ protected String getDefaultDigestAlgorithm() {
+ return defaultDigestAlgorithm;
+ }
+
+
+ /**
+ * Assigns the name of this realm, and stores it in the cache
+ * of realms. Used when initializing a newly created in-memory
+ * realm object; if the realm already has a name, there is no
+ * effect.
+ *
+ * @param name name to be assigned to this realm.
+ */
+ protected final void setName(String name) {
+ if (myName != null) {
+ return;
+ }
+ myName = name;
+ }
+
+
+ /**
+ * Returns the name of this realm.
+ *
+ * @return name of realm.
+ */
+ @Override
+ public String toString() {
+ return myName;
+ }
+
+
+ /**
+ * Compares a realm to another. The comparison first considers the
+ * authentication type, so that realms supporting the same kind of
+ * user authentication are grouped together. Then it compares realm
+ * realm names. Realms compare "before" other kinds of objects (i.e.
+ * there's only a partial order defined, in the case that those other
+ * objects compare themselves "before" a realm object).
+ */
+ public int compareTo (Object realm) {
+ if (!(realm instanceof Realm)) {
+ return 1;
+ }
+
+ Realm r = (Realm) realm;
+ String str = r.getAuthType ();
+ int temp;
+
+ if ((temp = getAuthType ().compareTo (str)) != 0) {
+ return temp;
+ }
+
+ str = r.getName ();
+ return getName ().compareTo (str);
+ }
+
+
+ /**
+ * Instantiate a Realm with the given name and properties using the
+ * Class name given. This method is used by iAS and not RI.
+ *
+ * @param name Name of the new realm.
+ * @param className Java Class name of the realm to create.
+ * @param props Properties containing values of the Property element
+ * from server.xml
+ * @returns Reference to the new Realm. The Realm class keeps an internal
+ * list of all instantiated realms.
+ * @throws BadRealmException If the requested realm cannot be instantiated.
+ *
+ */
+ public static synchronized Realm instantiate(String name, String className,
+ Properties props)
+ throws BadRealmException
+ {
+ //Register the realm provider
+ registerRealmStatsProvier();
+
+ Realm realmClass = _getInstance(name);
+ if(realmClass == null) {
+ realmClass = doInstantiate(name, className, props);
+ RealmsManager mgr = getRealmsManager();
+ mgr.putIntoLoadedRealms(name, realmClass);
+ }
+ return realmClass;
+ }
+
+ /**
+ * Instantiate a Realm with the given name and properties using the
+ * Class name given. This method is used by iAS and not RI.
+ *
+ * @param name Name of the new realm.
+ * @param className Java Class name of the realm to create.
+ * @param props Properties containing values of the Property element
+ * from server.xml
+ * @param configName the config to which this realm belongs
+ * @returns Reference to the new Realm. The Realm class keeps an internal
+ * list of all instantiated realms.
+ * @throws BadRealmException If the requested realm cannot be instantiated.
+ *
+ */
+ public static synchronized Realm instantiate(String name, String className,
+ Properties props, String configName)
+ throws BadRealmException
+ {
+ //Register the realm provider
+ registerRealmStatsProvier();
+
+ Realm realmClass = _getInstance(configName, name);
+ if(realmClass == null) {
+ realmClass = doInstantiate(name, className, props);
+ RealmsManager mgr = getRealmsManager();
+ mgr.putIntoLoadedRealms(configName, name, realmClass);
+ }
+ return realmClass;
+
+ }
+
+ private static void registerRealmStatsProvier() {
+ if (realmStatsProvier == null) {
+ getRealmStatsProvier();
+ StatsProviderManager.register("security", PluginPoint.SERVER, "security/realm", realmStatsProvier);
+ }
+ }
+
+ public static synchronized void getRealmStatsProvier(){
+ if(realmStatsProvier == null){
+ realmStatsProvier = new RealmStatsProvider();
+ }
+ }
+
+ /**
+ * Instantiate a Realm with the given name, loading properties from
+ * the given file. This method is only used by RI and is not called
+ * anywhere in iAS.
+ * Note : this method stands unused in V3.1 but keeping it since it is a
+ * public method.
+ * @deprecated
+ * @param realmName Name of the new realm.
+ * @param f File containing Properties for the new realm.
+ */
+ public static synchronized Realm instantiate(String realmName, File f)
+ throws NoSuchRealmException, BadRealmException, FileNotFoundException
+ {
+
+
+ if (!f.exists() || !f.isFile()) {
+ throw new FileNotFoundException ();
+ }
+
+ if(_getInstance(realmName) != null) {
+ throw new BadRealmException(
+ localStrings.getLocalString("realm.already_exists",
+ "This Realm already exists."));
+ }
+
+ //
+ // First load the description from properties.
+ //
+ InputStream in = null;
+ Properties props = new Properties();
+
+ try{
+ in = new FileInputStream(f);
+ props.load(in);
+ //
+ // Then instantiate and initialize, using the single mandatory
+ // property ("classname").
+ //
+ String classname = props.getProperty("classname");
+ assert (classname != null);
+
+ return doInstantiate(realmName, classname, props);
+ } catch (IOException e) {
+ throw new BadRealmException(e.toString());
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch(Exception ex) {
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Instantiates a Realm class of the given type and invokes its init()
+ *
+ */
+ private static synchronized Realm doInstantiate(String name, String className,
+ Properties props)
+ throws BadRealmException
+ {
+
+ ServiceLocator habitat = Globals.getDefaultHabitat();
+ RealmsManager mgr = null;
+ try {
+ mgr = getRealmsManager();
+ Class realmClass = null;
+ //try a HK2 route first
+ Realm r = habitat.getService(Realm.class, name);
+ if (r == null) {
+ try {
+ //TODO: workaround here. Once fixed in V3 we should be able to use
+ //Context ClassLoader instead.
+ ClassLoaderHierarchy hierarchy =
+ habitat.getService(ClassLoaderHierarchy.class);
+ realmClass = hierarchy.getCommonClassLoader().loadClass(className);
+ Object obj = realmClass.newInstance();
+ r = (Realm) obj;
+ } catch (ClassNotFoundException ex) {
+ realmClass = Class.forName(className);
+ Object obj = realmClass.newInstance();
+ r = (Realm) obj;
+ }
+ }
+
+ r.setName(name);
+ r.init(props);
+ if (mgr == null) {
+ throw new BadRealmException("Unable to locate RealmsManager Service");
+ }
+ _logger.log(Level.INFO, SecurityLoggerInfo.realmCreated ,new Object[]{name, className});
+ return r;
+
+
+ } catch (NoSuchRealmException ex) {
+ throw new BadRealmException(ex);
+ } catch (InstantiationException ex) {
+ throw new BadRealmException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new BadRealmException(ex);
+ } catch (ClassNotFoundException ex) {
+ throw new BadRealmException(ex);
+ }
+ }
+
+
+ /**
+ * Replace a Realm instance. Can be used by a Realm subclass to
+ * replace a previously initialized instance of itself. Future
+ * getInstance requests will then obtain the new instance.
+ *
+ * <P>Minimal error checking is done. The realm being replaced must
+ * already exist (instantiate() was previously called), the new
+ * instance must be fully initialized properly and it must of course
+ * be of the same class as the previous instance.
+ *
+ * @param realm The new realm instance.
+ * @param name The (previously instantiated) name for this realm.
+ *
+ */
+ protected static synchronized void updateInstance(Realm realm, String name)
+ {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr == null) {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+
+ Realm oldRealm = mgr.getFromLoadedRealms(name);
+ if (!oldRealm.getClass().equals(realm.getClass())) {
+ // would never happen unless bug in realm subclass
+ throw new Error("Incompatible class "+realm.getClass()+
+ " in replacement realm "+name);
+ }
+ realm.setName(oldRealm.getName());
+ mgr.putIntoLoadedRealms(name, realm);
+ _logger.log(Level.INFO, SecurityLoggerInfo.realmUpdated, new Object[]{realm.getName()});
+ }
+
+ /**
+ * Replace a Realm instance. Can be used by a Realm subclass to
+ * replace a previously initialized instance of itself. Future
+ * getInstance requests will then obtain the new instance.
+ *
+ * <P>Minimal error checking is done. The realm being replaced must
+ * already exist (instantiate() was previously called), the new
+ * instance must be fully initialized properly and it must of course
+ * be of the same class as the previous instance.
+ *
+ * @param realm The new realm instance.
+ * @param name The (previously instantiated) name for this realm.
+ *
+ */
+ protected static synchronized void updateInstance(String configName, Realm realm, String name) {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr == null) {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+
+ Realm oldRealm = mgr.getFromLoadedRealms(configName, name);
+ if (!oldRealm.getClass().equals(realm.getClass())) {
+ // would never happen unless bug in realm subclass
+ throw new Error("Incompatible class " + realm.getClass()
+ + " in replacement realm " + name);
+ }
+ realm.setName(oldRealm.getName());
+ mgr.putIntoLoadedRealms(configName, name, realm);
+ _logger.log(Level.INFO, SecurityLoggerInfo.realmUpdated, new Object[]{realm.getName()});
+ }
+
+
+ /**
+ * Convenience method which returns the Realm object representing
+ * the current default realm. Equivalent to
+ * getInstance(getDefaultRealm()).
+ *
+ * @return Realm representing default realm.
+ * @exception NoSuchRealmException if default realm does not exist
+ */
+ public static synchronized Realm getDefaultInstance() throws NoSuchRealmException
+ {
+ return getInstance(getDefaultRealm());
+ }
+
+
+ /**
+ * Returns the name of the default realm.
+ *
+ * @return Default realm name.
+ *
+ */
+ public static synchronized String getDefaultRealm() {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr.getDefaultRealmName();
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ }
+
+
+ /**
+ * Sets the name of the default realm.
+ *
+ * @param realmName Name of realm to set as default.
+ *
+ */
+ public static synchronized void setDefaultRealm(String realmName) {
+ //defaultRealmName = realmName;
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ mgr.setDefaultRealmName(realmName);
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ }
+
+ /**
+ * Remove realm with given name from cache.
+ * @param realmName
+ * @exception NoSuchRealmException
+ */
+ public static synchronized void unloadInstance(String realmName) throws NoSuchRealmException {
+ //make sure instance exist
+ getInstance(realmName);
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ mgr.removeFromLoadedRealms(realmName);
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ _logger.log(Level.INFO, SecurityLoggerInfo.realmDeleted, realmName);
+ }
+
+ /**
+ * Remove realm with given name from cache.
+ * @param realmName
+ * @exception NoSuchRealmException
+ */
+ public static synchronized void unloadInstance(String configName, String realmName) throws NoSuchRealmException {
+ //make sure instance exist
+ //getInstance(configName, realmName);
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ mgr.removeFromLoadedRealms(configName, realmName);
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ _logger.log(Level.INFO, SecurityLoggerInfo.realmDeleted, realmName);
+ }
+
+
+
+ /**
+ * Set a realm property.
+ *
+ * @param name property name.
+ * @param value property value.
+ *
+ */
+ public synchronized void setProperty(String name, String value)
+ {
+ ctxProps.setProperty(name, value);
+ }
+
+
+ /**
+ * Get a realm property.
+ *
+ * @param name property name.
+ * @returns value.
+ *
+ */
+ public synchronized String getProperty(String name)
+ {
+ return ctxProps.getProperty(name);
+ }
+
+ /**
+ * Return properties of the realm.
+ */
+ protected synchronized Properties getProperties() {
+ return ctxProps;
+ }
+
+
+ /**
+ * Returns name of JAAS context used by this realm.
+ *
+ * <P>The JAAS context is defined in server.xml auth-realm element
+ * associated with this realm.
+ *
+ * @return String containing JAAS context name.
+ *
+ */
+ public synchronized String getJAASContext()
+ {
+ return ctxProps.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
+ }
+
+
+ /**
+ * Returns the realm identified by the name which is passed
+ * as a parameter. This function knows about all the realms
+ * which exist; it is not possible to store (or create) one
+ * which is not accessible through this routine.
+ *
+ * @param name identifies the realm
+ * @return the requested realm
+ * @exception NoSuchRealmException if the realm is invalid
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public static synchronized Realm getInstance(String name) throws NoSuchRealmException
+ {
+ Realm retval = _getInstance(name);
+
+ if (retval == null) {
+ throw new NoSuchRealmException(
+ localStrings.getLocalString("realm.no_such_realm",
+ name + " realm does not exist.",
+ new Object[] { name }));
+ }
+
+ return retval;
+ }
+
+ /**
+ * Returns the realm identified by the name which is passed
+ * as a parameter. This function knows about all the realms
+ * which exist; it is not possible to store (or create) one
+ * which is not accessible through this routine.
+ *
+ * @param name identifies the realm
+ * @return the requested realm
+ * @exception NoSuchRealmException if the realm is invalid
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public static synchronized Realm getInstance(String configName, String name) throws NoSuchRealmException
+ {
+ Realm retval = _getInstance(configName, name);
+
+ if (retval == null) {
+ throw new NoSuchRealmException(
+ localStrings.getLocalString("realm.no_such_realm",
+ name + " realm does not exist.",
+ new Object[] { name }));
+ }
+
+ return retval;
+ }
+
+ /**
+ * This is a private method for getting realm instance.
+ * If realm does not exist, then it will not return null rather than
+ * throw exception.
+ * @param name identifies the realm
+ * @return the requested realm
+ */
+ private static synchronized Realm _getInstance(String name) {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr._getInstance(name);
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ }
+
+ /**
+ * This is a private method for getting realm instance.
+ * If realm does not exist, then it will not return null rather than
+ * throw exception.
+ * @param name identifies the realm
+ * @return the requested realm
+ */
+ private static synchronized Realm _getInstance(String configName, String name) {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr._getInstance(configName, name);
+ } else {
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+ }
+
+
+ /**
+ * Returns the names of accessible realms.
+ * @return set of realm names
+ */
+ public static synchronized Enumeration getRealmNames() {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr.getRealmNames();
+ }
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+
+
+ /**
+ * The default constructor creates a realm which will later
+ * be initialized, either from properties or by deserializing.
+ */
+ protected Realm() {
+ ctxProps = new Properties();
+ }
+
+
+ /**
+ * Initialize a realm with some properties. This can be used
+ * when instantiating realms from their descriptions. This
+ * method may only be called a single time.
+ *
+ * @param props initialization parameters used by this realm.
+ * @exception BadRealmException if the configuration parameters
+ * identify a corrupt realm
+ * @exception NoSuchRealmException if the configuration parameters
+ * specify a realm which doesn't exist
+ */
+ protected void init(Properties props)
+ throws BadRealmException, NoSuchRealmException {
+ String groupList = props.getProperty(PARAM_GROUPS);
+ if (groupList != null && groupList.length() > 0) {
+ this.setProperty(PARAM_GROUPS, groupList);
+ assignGroups = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer(groupList, GROUPS_SEP);
+ while (st.hasMoreTokens()) {
+ String grp = (String)st.nextToken();
+ if (!assignGroups.contains(grp)) {
+ assignGroups.add(grp);
+ }
+ }
+ }
+ String groupMapping = props.getProperty(PARAM_GROUP_MAPPING);
+ if (groupMapping != null) {
+ groupMapper = new GroupMapper();
+ groupMapper.parse(groupMapping);
+ }
+ String defaultDigestAlgo = null;
+ if(_getRealmsManager() != null) {
+ defaultDigestAlgo = _getRealmsManager().getDefaultDigestAlgorithm();
+ }
+ this.defaultDigestAlgorithm = (defaultDigestAlgo == null)?DEFAULT_DEF_DIG_ALGO_VAL:defaultDigestAlgo;
+ }
+
+ private static synchronized RealmsManager _getRealmsManager() {
+ if (realmsManager.get() == null) {
+ if(Globals.getDefaultHabitat() != null) {
+ realmsManager = new WeakReference<RealmsManager>(Globals.get(RealmsManager.class));
+ }
+ else {
+ return null;
+ }
+ }
+ return realmsManager.get();
+ }
+
+ private static RealmsManager getRealmsManager() {
+ if (realmsManager.get() != null) {
+ return realmsManager.get();
+ }
+ return _getRealmsManager();
+ }
+ /**
+ * Checks if the given realm name is loaded/valid.
+ * @param String name of the realm to check.
+ * @return true if realm present, false otherwise.
+ */
+ public static boolean isValidRealm(String name) {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr.isValidRealm(name);
+ }
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+
+ /**
+ * Checks if the given realm name is loaded/valid.
+ * @param String name of the realm to check.
+ * @return true if realm present, false otherwise.
+ */
+ public static boolean isValidRealm(String configName, String name) {
+ RealmsManager mgr = getRealmsManager();
+ if (mgr != null) {
+ return mgr.isValidRealm(configName, name);
+ }
+ throw new RuntimeException("Unable to locate RealmsManager Service");
+ }
+
+ /**
+ * Add assign groups to given Vector of groups.
+ * To be used by getGroupNames.
+ * @param grps
+ */
+ protected String[] addAssignGroups(String[] grps) {
+ String[] resultGroups = grps;
+ if (assignGroups != null && assignGroups.size() > 0) {
+ List<String> groupList = new ArrayList<String>();
+ if (grps != null && grps.length > 0) {
+ for (String grp : grps) {
+ groupList.add(grp);
+ }
+ }
+
+ for (String agrp : assignGroups) {
+ if (!groupList.contains(agrp)) {
+ groupList.add(agrp);
+ }
+ }
+ resultGroups = groupList.toArray(new String[groupList.size()]);
+ }
+ return resultGroups;
+ }
+
+ protected ArrayList<String> getMappedGroupNames(String group) {
+ if (groupMapper != null) {
+ ArrayList<String> result = new ArrayList<String>();
+ groupMapper.getMappedGroups(group, result);
+ return result;
+ }
+ return null;
+ }
+
+ //---[ Abstract methods ]------------------------------------------------
+
+
+ /**
+ * Returns a short (preferably less than fifteen characters) description
+ * of the kind of authentication which is supported by this realm.
+ *
+ * @return description of the kind of authentication that is directly
+ * supported by this realm.
+ */
+ public abstract String getAuthType ();
+
+ /**
+ * Returns an AuthenticationHandler object which can be used to
+ * authenticate within this realm.
+ *
+ * @return An AuthenticationHandler object for this realm.
+ */
+ public abstract AuthenticationHandler getAuthenticationHandler ();
+
+ /**
+ * Returns names of all the users in this particular realm.
+ *
+ * @return enumeration of user names (strings)
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public abstract Enumeration getUserNames() throws BadRealmException;
+
+ /**
+ * Returns the information recorded about a particular named user.
+ *
+ * @param name name of the user whose information is desired
+ * @return the user object
+ * @exception NoSuchUserException if the user doesn't exist
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public abstract User getUser(String name)
+ throws NoSuchUserException, BadRealmException;
+
+ /**
+ * Returns names of all the groups in this particular realm.
+ *
+ * @return enumeration of group names (strings)
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public abstract Enumeration getGroupNames()
+ throws BadRealmException;
+
+ /**
+ * Returns the name of all the groups that this user belongs to
+ * @param username name of the user in this realm whose group listing
+ * is needed.
+ * @return enumeration of group names (strings)
+ * @exception InvalidOperationException thrown if the realm does not
+ * support this operation - e.g. Certificate realm does not support this
+ * operation
+ */
+ public abstract Enumeration getGroupNames (String username)
+ throws InvalidOperationException, NoSuchUserException;
+
+ /**
+ * Refreshes the realm data so that new users/groups are visible.
+ *
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public abstract void refresh() throws BadRealmException;
+
+ /**
+ * Refreshes the realm data so that new users/groups are visible.
+ *
+ * @exception BadRealmException if realm data structures are bad
+ */
+ public void refresh(String configName) throws BadRealmException {
+ //do nothing
+ }
+
+ /**
+ * Adds new user to file realm. User cannot exist already.
+ *
+ * @param name User name.
+ * @param password Cleartext password for the user.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ *
+ */
+ public abstract void addUser(String name, char[] password, String[] groupList)
+ throws BadRealmException, IASSecurityException;
+
+ /**
+ * Remove user from file realm. User must exist.
+ *
+ * @param name User name.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ public abstract void removeUser(String name)
+ throws NoSuchUserException, BadRealmException;
+
+ /**
+ * Update data for an existing user. User must exist.
+ *
+ * @param name Current name of the user to update.
+ * @param newName New name to give this user. It can be the same as
+ * the original name. Otherwise it must be a new user name which
+ * does not already exist as a user.
+ * @param password Cleartext password for the user. If non-null the user
+ * password is changed to this value. If null, the original password
+ * is retained.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ public abstract void updateUser(String name, String newName, char[] password,
+ String[] groups)
+ throws NoSuchUserException, BadRealmException,
+ IASSecurityException;
+ /**
+ * @return true if the realm implementation support User Management (add,remove,update user)
+ */
+ public abstract boolean supportsUserManagement();
+
+ /**
+ * Persist the realm data to permanent storage
+ * @throws com.sun.enterprise.security.auth.realm.BadRealmException
+ */
+ public abstract void persist() throws BadRealmException;
+}
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmConfig.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmConfig.java
new file mode 100644
index 0000000..f4f3269
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmConfig.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+
+import org.jvnet.hk2.config.types.Property;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * RealmConfig usable by standalone : Admin CLI for creating Realms
+ * It has a subset of functionality defined in com.sun.enterprise.security.RealmConfig
+ */
+public class RealmConfig {
+
+ private static Logger logger =
+ SecurityLoggerInfo.getLogger();
+
+ public static void createRealms(String defaultRealm, List<AuthRealm> realms) {
+ createRealms(defaultRealm, realms, null);
+ }
+ public static void createRealms(String defaultRealm, List<AuthRealm> realms, String configName) {
+ assert(realms != null);
+
+ String goodRealm = null; // need at least one good realm
+
+ for (AuthRealm aRealm : realms) {
+ String realmName = aRealm.getName();
+ String realmClass = aRealm.getClassname();
+ assert (realmName != null);
+ assert (realmClass != null);
+
+ try {
+ List<Property> realmProps = aRealm.getProperty();
+ /*V3 Commented ElementProperty[] realmProps =
+ aRealm.getElementProperty();*/
+ Properties props = new Properties();
+ for (Property realmProp : realmProps) {
+ props.setProperty(realmProp.getName(), realmProp.getValue());
+ }
+ Realm.instantiate(realmName, realmClass, props, configName);
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Configured realm: " + realmName);
+ }
+
+ if (goodRealm == null) {
+ goodRealm = realmName;
+ }
+ } catch (Exception e) {
+ logger.log(Level.WARNING,
+ SecurityLoggerInfo.realmConfigDisabledError, realmName);
+ logger.log(Level.WARNING, SecurityLoggerInfo.securityExceptionError, e);
+ }
+ }
+
+ // done loading all realms, check that there is at least one
+ // in place and that default is installed, or change default
+ // to the first one loaded (arbitrarily).
+
+ if (goodRealm == null) {
+ logger.severe(SecurityLoggerInfo.noRealmsError);
+
+ } else {
+ try {
+ Realm.getInstance(defaultRealm);
+ } catch (Exception e) {
+ defaultRealm = goodRealm;
+ }
+ Realm.setDefaultRealm(defaultRealm);
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("Default realm is set to: " + defaultRealm);
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmStatsProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmStatsProvider.java
new file mode 100644
index 0000000..75e1220
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmStatsProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import org.glassfish.external.statistics.CountStatistic;
+import org.glassfish.external.statistics.impl.CountStatisticImpl;
+import org.glassfish.external.probe.provider.annotations.ProbeListener;
+import org.glassfish.external.probe.provider.annotations.ProbeParam;
+
+
+import org.glassfish.gmbal.*;
+/**
+ *
+ * @author nithyasubramanian
+ */
+@AMXMetadata(type="security-realm-mon", group="monitoring", isSingleton=false)
+@ManagedObject
+@Description( "Security Realm Statistics" )
+public class RealmStatsProvider {
+
+ private CountStatisticImpl realmCount;
+
+
+ public RealmStatsProvider() {
+ realmCount = new CountStatisticImpl("RealmCount", "realm","No of Realms");
+ }
+
+ @ManagedAttribute
+ @Description( "Security Realm Count" )
+ public CountStatistic getRealmCount() {
+ return realmCount;
+ }
+
+ @ProbeListener("glassfish:security:realm:realmAddedEvent")
+ public void realmAddedEvent(@ProbeParam("realmName")String realmName){
+ realmCount.increment();
+ }
+
+ @ProbeListener("glassfish:security:realm:realmRemovedEvent")
+ public void realmRemovedEvent(@ProbeParam("realmName")String realmName){
+ realmCount.decrement();
+ }
+
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsManager.java
new file mode 100644
index 0000000..4fef3a4
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsManager.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.hk2.api.ActiveDescriptor;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.hk2.utilities.BuilderHelper;
+import org.glassfish.internal.api.Globals;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.types.Property;
+
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+
+/**
+ *
+ * @author kumar.jayanti
+ */
+@Service
+@Singleton
+public class RealmsManager {
+ //per domain list of loaded Realms
+ //Wanted to get rid of Hashtable but the API exporting Enumeration<String> is preventing
+ // it for now.
+ private final Map<String, Hashtable<String, Realm>> loadedRealms =
+ Collections.synchronizedMap(new HashMap<String, Hashtable<String, Realm>>());
+
+ // Keep track of name of default realm for this domain. This is updated during startup
+ // using value from server.xml
+ private volatile String defaultRealmName="default";
+ private final RealmsProbeProvider probeProvider = new RealmsProbeProvider();
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ private String defaultDigestAlgorithm = null;
+
+ private static final String DEFAULT_DIGEST_ALGORITHM = "default-digest-algorithm";
+
+
+ public RealmsManager() {
+
+ }
+ /**
+ * Checks if the given realm name is loaded/valid.
+ * @param name of the realm to check.
+ * @return true if realm present, false otherwise.
+ */
+ public boolean isValidRealm(String name){
+ if(name == null){
+ return false;
+ } else {
+ return configContainsRealm(name, config.getName());
+ }
+ }
+
+ /**
+ * Checks if the given realm name is loaded/valid.
+ * @param name of the realm to check.
+ * @return true if realm present, false otherwise.
+ */
+ public boolean isValidRealm(String configName, String name){
+ if(name == null){
+ return false;
+ } else {
+ return configContainsRealm(name, configName);
+ }
+ }
+
+ /**
+ * Returns the names of accessible realms.
+ * @return set of realm names
+ */
+ public Enumeration<String> getRealmNames() {
+ return getRealmNames(config.getName());
+ }
+
+ Realm _getInstance(String configName, String name) {
+ Realm retval = null;
+ retval = configGetRealmInstance(configName, name);
+
+ // Some tools as well as numerous other locations assume that
+ // getInstance("default") always works; keep them from breaking
+ // until code can be properly cleaned up. 4628429
+
+ // Also note that for example the appcontainer will actually create
+ // a Subject always containing realm='default' so this notion
+ // needs to be fixed/handled.
+ if ( (retval == null) && (Realm.RI_DEFAULT.equals(name)) ) {
+ retval = configGetRealmInstance(configName,getDefaultRealmName());
+ }
+
+ return retval;
+ }
+
+ Realm _getInstance(String name) {
+ return _getInstance(config.getName(), name);
+ }
+
+ public void removeFromLoadedRealms(String realmName) {
+ Realm r = removeFromLoadedRealms(config.getName(), realmName);
+ if (r != null) {
+ probeProvider.realmRemovedEvent(realmName);
+ }
+ }
+
+ void putIntoLoadedRealms(String realmName, Realm realm) {
+ putIntoLoadedRealms(config.getName(), realmName, realm);
+ probeProvider.realmAddedEvent(realmName);
+ }
+
+ public Realm getFromLoadedRealms(String realmName) {
+ return configGetRealmInstance(config.getName(),realmName);
+ }
+
+ public Realm getFromLoadedRealms(String configName, String realmName) {
+ return configGetRealmInstance(configName,realmName);
+ }
+
+ public synchronized String getDefaultRealmName() {
+ return defaultRealmName;
+ }
+
+ public synchronized void setDefaultRealmName(String defaultRealmName) {
+ this.defaultRealmName = defaultRealmName;
+ }
+
+ /**
+ * Returns names of predefined AuthRealms' classes supported by security service.
+ * @returns array of predefind AuthRealms' classes
+ *
+ */
+ public List<String> getPredefinedAuthRealmClassNames()
+ {
+ //!!!!!!!!!!!! (hardcoded for now until ss will implement backemnd support)
+ /* return new String[]{
+ "com.sun.enterprise.security.auth.realm.file.FileRealm",
+ "com.sun.enterprise.security.auth.realm.certificate.CertificateRealm",
+ "com.sun.enterprise.security.auth.realm.ldap.LDAPRealm",
+ "com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm",
+ "com.sun.enterprise.security.auth.realm.solaris.SolarisRealm"};*/
+ ServiceLocator habitat = Globals.getDefaultHabitat();
+ List<ActiveDescriptor<?>> collection = habitat.getDescriptors(
+ BuilderHelper.createContractFilter(Realm.class.getName()));
+ List<String> arr = new ArrayList<String>();
+ for (ActiveDescriptor<?> it : collection) {
+ arr.add(it.getImplementation());
+ }
+
+ return arr;
+ }
+
+ public void createRealms() {
+ createRealms(config.getSecurityService(), config);
+ }
+
+ public void createRealms(Config cfg) {
+ if (cfg == null) {
+ return;
+ }
+ createRealms(cfg.getSecurityService(), cfg);
+ }
+
+ private void setDefaultDigestAlgorithm() {
+ SecurityService service = config.getSecurityService();
+ if(service == null) {
+ return;
+ }
+ List<Property> props = service.getProperty();
+ if(props == null) {
+ return;
+ }
+ Iterator<Property> propsIterator = props.iterator();
+ while(propsIterator != null && propsIterator.hasNext()) {
+ Property prop = propsIterator.next();
+ if(prop != null && DEFAULT_DIGEST_ALGORITHM.equals(prop.getName())) {
+ this.defaultDigestAlgorithm = prop.getValue();
+ break;
+ }
+ }
+ }
+
+ public String getDefaultDigestAlgorithm() {
+ return defaultDigestAlgorithm;
+ }
+
+ /**
+ * Load all configured realms from server.xml and initialize each
+ * one. Initialization is done by calling Realm.initialize() with
+ * its name, class and properties. The name of the default realm
+ * is also saved in the Realm class for reference during server
+ * operation.
+ *
+ * <P>This method superceeds the RI RealmManager.createRealms() method.
+ *
+ * */
+ private void createRealms(SecurityService securityBean, Config cfg) {
+ //check if realms are already loaded by admin GUI ?
+ if (realmsAlreadyLoaded(cfg.getName())) {
+ return;
+ }
+
+ setDefaultDigestAlgorithm();
+ try {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("Initializing configured realms from SecurityService in Domain.xml....");
+ }
+
+ if (securityBean == null) {
+ securityBean = cfg.getSecurityService();
+ assert (securityBean != null);
+ }
+
+ // grab default realm name
+ String defaultRealm = securityBean.getDefaultRealm();
+
+ // get set of auth-realms and process each
+ List<AuthRealm> realms = securityBean.getAuthRealm();
+ assert (realms != null);
+
+ RealmConfig.createRealms(defaultRealm, realms, cfg.getName());
+
+ } catch (Exception e) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.noRealmsError, e);
+ }
+ }
+
+ private boolean realmsAlreadyLoaded(String cfgName) {
+ Enumeration<String> en = getRealmNames(cfgName);
+ return (en != null && en.hasMoreElements()) ? true : false;
+ }
+
+ private boolean configContainsRealm(String name, String configName) {
+ Hashtable<String, Realm> containedRealms = loadedRealms.get(configName);
+ return (containedRealms != null) ? containedRealms.containsKey(name) : false;
+ }
+
+ private Enumeration<String> getRealmNames(String configName) {
+ Hashtable<String, Realm> containedRealms = loadedRealms.get(configName);
+ return (containedRealms != null) ? containedRealms.keys() : null;
+ }
+
+ private Realm configGetRealmInstance(String configName, String realm) {
+ Hashtable<String, Realm> containedRealms = loadedRealms.get(configName);
+ return (containedRealms != null) ? (Realm) containedRealms.get(realm) : null;
+ }
+
+ public Realm removeFromLoadedRealms (String configName, String realmName) {
+ Hashtable<String, Realm> containedRealms = loadedRealms.get(configName);
+ return (containedRealms != null) ?(Realm)containedRealms.remove(realmName) : null;
+ }
+
+ public void putIntoLoadedRealms (String configName, String realmName, Realm realm) {
+ Hashtable<String, Realm> containedRealms = loadedRealms.get(configName);
+ if (containedRealms == null) {
+ containedRealms = new Hashtable<String, Realm>();
+ if (configName == null) {
+ configName = config.getName();
+ }
+ loadedRealms.put(configName, containedRealms);
+ }
+ containedRealms.put(realmName, realm);
+ }
+
+ public void refreshRealm(String configName, String realmName) {
+ if (realmName != null && realmName.length() > 0) {
+ try {
+ Realm realm = Realm.getInstance(configName, realmName);
+
+ if (realm != null) {
+ realm.refresh(configName);
+ }
+ } catch (com.sun.enterprise.security.auth.realm.NoSuchRealmException nre) {
+ // _logger.fine("Realm: "+realmName+" is not configured");
+ } catch (com.sun.enterprise.security.auth.realm.BadRealmException bre) {
+ // _logger.fine("Realm: "+realmName+" is not configured");
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsProbeProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsProbeProvider.java
new file mode 100644
index 0000000..8a60005
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/RealmsProbeProvider.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+import org.glassfish.external.probe.provider.annotations.ProbeProvider;
+import org.glassfish.external.probe.provider.annotations.Probe;
+import org.glassfish.external.probe.provider.annotations.ProbeParam;
+
+/**
+ *
+ * @author nithyasubramanian
+ */
+@ProbeProvider(moduleProviderName="glassfish",moduleName="security",probeProviderName="realm")
+public class RealmsProbeProvider {
+
+ @Probe(name="realmAddedEvent")
+ public void realmAddedEvent(
+ @ProbeParam("realmName") String realmName
+ )
+ {}
+
+ @Probe(name="realmRemovedEvent")
+ public void realmRemovedEvent(
+ @ProbeParam("realmName") String realmName
+ )
+ {}
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/User.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/User.java
new file mode 100644
index 0000000..7be8e82
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/User.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm;
+
+import java.security.Principal;
+
+import java.util.Enumeration;
+
+
+/**
+ * All users are principals ... perhaps in the native OS, perhaps
+ * not.
+ *
+ * <P> Users always have authentication information, which is used
+ * to validate a user's proferred credentials. Different kinds of
+ * realms use different kinds of authentication information. For
+ * example, realms could use X.509 public key certificates, shared
+ * passphrases, encrypted passwords, smart cards, or biometric data
+ * to figure out if the user's credentials are valid.
+ *
+ * <P> Users typically have attributes that identify privileges
+ * granted/possesed by the user.
+ *
+ * @author Harish Prabandham
+ */
+
+public interface User extends Principal {
+ /**
+ * Returns the realm with which this user is associated.
+ */
+ Realm getRealm () throws NoSuchRealmException;
+
+
+ /**
+ * Returns the single requested attribute for the user.
+ *
+ * @param name string identifying the attribute.
+ * @return value of that attribute, or null if no value
+ * has been defined
+ */
+ Object getAttribute (String name);
+
+
+ /**
+ * Returns an enumeration of the keys for the attributes
+ * supported for this user.
+ */
+ Enumeration getAttributeNames ();
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/certificate/CertificateRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/certificate/CertificateRealm.java
new file mode 100644
index 0000000..7870bb2
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/certificate/CertificateRealm.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.certificate;
+
+import com.sun.enterprise.security.SecurityContext;
+import com.sun.enterprise.security.auth.login.DistinguishedPrincipalCredential;
+import java.util.*;
+import java.util.logging.Level;
+
+import javax.security.auth.Subject;
+
+import org.glassfish.security.common.Group;
+//import com.sun.enterprise.security.SecurityContext;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.InvalidOperationException;
+
+import com.sun.enterprise.security.auth.realm.IASRealm;
+import java.security.Principal;
+import javax.security.auth.callback.Callback;
+
+
+import org.jvnet.hk2.annotations.Service;
+import sun.security.x509.X500Name;
+
+
+/**
+ * Realm wrapper for supporting certificate authentication.
+ *
+ * <P>The certificate realm provides the security-service functionality
+ * needed to process a client-cert authentication. Since the SSL processing,
+ * and client certificate verification is done by NSS, no authentication
+ * is actually done by this realm. It only serves the purpose of being
+ * registered as the certificate handler realm and to service group
+ * membership requests during web container role checks.
+ *
+ * <P>There is no JAAS LoginModule corresponding to the certificate realm,
+ * therefore this realm does not require the jaas-context configuration
+ * parameter to be set. The purpose of a JAAS LoginModule is to implement
+ * the actual authentication processing, which for the case of this
+ * certificate realm is already done by the time execution gets to Java.
+ *
+ * <P>The certificate realm needs the following properties in its
+ * configuration: None.
+ *
+ * <P>The following optional attributes can also be specified:
+ * <ul>
+ * <li>assign-groups - A comma-separated list of group names which
+ * will be assigned to all users who present a cryptographically
+ * valid certificate. Since groups are otherwise not supported
+ * by the cert realm, this allows grouping cert users
+ * for convenience.
+ * </ul>
+ *
+ */
+
+@Service
+public final class CertificateRealm extends IASRealm
+{
+ // Descriptive string of the authentication type of this realm.
+ public static final String AUTH_TYPE = "certificate";
+ private Vector<String> defaultGroups = new Vector<String>();
+
+ // Optional link to a realm to verify group (possibly user, later)
+ // public static final String PARAM_USEREALM = "use-realm";
+
+ // Optional ordered list of possible elements to use as user name
+ // from X.500 name.
+ // public static final String PARAM_NAMEFIELD = "name-field";
+ // private String[] nameFields = null;
+ // private static final String LINK_SEP = ",";
+
+ /**
+ * Initialize a realm with some properties. This can be used
+ * when instantiating realms from their descriptions. This
+ * method is invoked from Realm during initialization.
+ *
+ * @param props Initialization parameters used by this realm.
+ * @exception BadRealmException If the configuration parameters
+ * identify a corrupt realm.
+ * @exception NoSuchRealmException If the configuration parameters
+ * specify a realm which doesn't exist.
+ *
+ */
+ protected void init(Properties props)
+ throws BadRealmException, NoSuchRealmException
+ {
+ super.init(props);
+ String[] groups = addAssignGroups(null);
+ if (groups != null && groups.length > 0) {
+ for (String gp : groups) {
+ defaultGroups.add(gp);
+ }
+ }
+
+ String jaasCtx = props.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
+ if (jaasCtx != null) {
+ this.setProperty(IASRealm.JAAS_CONTEXT_PARAM, jaasCtx);
+ }
+
+
+ /* future enhacement; allow using subset of DN as name field;
+ requires RI fixes to handle subject & principal names
+ consistently
+ String nameLink = props.getProperty(PARAM_NAMEFIELD);
+ if (nameLink == null) {
+ Util.debug(log, "CertificateRealm: No "+PARAM_NAMEFIELD+
+ " provided, will use X.500 name.");
+ } else {
+
+ StringTokenizer st = new StringTokenizer(nameLink, LINK_SEP);
+ int n = st.countTokens();
+ nameFields = new String[n];
+
+ for (int i=0; i<n; i++) {
+ nameFields[i] = (String)st.nextToken();
+ }
+ }
+ */
+
+ /* future enhancement; allow linking to other realm such that
+ user presence verification and group membership can be
+ defined/shared; requires RI fixes to consistently check role
+ memberships and RI fixes to allow multiple active realms.
+ String link = props.getProperty(PARAM_USEREALM);
+ if (link != null) {
+ this.setProperty(PARAM_USEREALM, link);
+ Util.debug(log, "CertificateRealm : "+PARAM_USEREALM+"="+link);
+ }
+ */
+ }
+
+
+ /**
+ * Returns a short (preferably less than fifteen characters) description
+ * of the kind of authentication which is supported by this realm.
+ *
+ * @return Description of the kind of authentication that is directly
+ * supported by this realm.
+ */
+ public String getAuthType()
+ {
+ return AUTH_TYPE;
+ }
+
+
+ /**
+ * Returns the name of all the groups that this user belongs to.
+ *
+ * @param username Name of the user in this realm whose group listing
+ * is needed.
+ * @return Enumeration of group names (strings).
+ * @exception InvalidOperationException thrown if the realm does not
+ * support this operation - e.g. Certificate realm does not support
+ * this operation.
+ *
+ */
+ public Enumeration getGroupNames(String username)
+ throws NoSuchUserException, InvalidOperationException
+ {
+ // This is called during web container role check, not during
+ // EJB container role cheks... fix RI for consistency.
+
+ // Groups for cert users is empty by default unless some assign-groups
+ // property has been specified (see init()).
+ return defaultGroups.elements();
+ }
+
+
+ /**
+ * Returns name of JAAS context used by this realm. Overrides default
+ * Realm behavior of this method. The certificate realm does not
+ * require (or support) a LoginModule. This method should never get
+ * called unless there is a configuration error, so this overloading
+ * is provided to log an error message. See class documentation.
+ *
+ * @return null
+ *
+ */
+ /*public String getJAASContext()
+ {
+ _logger.warning("certrealm.nojaas");
+ return null;
+ }*/
+
+ /**
+ * Complete authentication of certificate user.
+ *
+ * <P>As noted, the certificate realm does not do the actual
+ * authentication (signature and cert chain validation) for
+ * the user certificate, this is done earlier in NSS. This method
+ * simply sets up the security context for the user in order to
+ * properly complete the authentication processing.
+ *
+ * <P>If any groups have been assigned to cert-authenticated users
+ * through the assign-groups property these groups are added to
+ * the security context for the current user.
+ *
+ * @param subject The Subject object for the authentication request.
+ * @param x500name The X500Name object from the user certificate.
+ *
+
+ public void authenticate(Subject subject, X500Name x500name)
+ {
+ // It is important to use x500name.getName() in order to be
+ // consistent with web containers view of the name - see bug
+ // 4646134 for reasons why this matters.
+
+ String name = x500name.getName();
+
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.finest(
+ "Certificate realm setting up security context for: "+ name);
+ }
+
+ if (defaultGroups != null) {
+ Set principalSet = subject.getPrincipals();
+ Enumeration e = defaultGroups.elements();
+ while (e.hasMoreElements()) {
+ principalSet.add(new Group((String) e.nextElement()));
+ }
+ }
+
+ SecurityContext securityContext =
+ new SecurityContext(name, subject);
+
+ SecurityContext.setCurrent(securityContext);
+ }*/
+
+ /**
+ * Complete authentication of certificate user.
+ *
+ * <P>As noted, the certificate realm does not do the actual
+ * authentication (signature and cert chain validation) for
+ * the user certificate, this is done earlier in NSS. This method
+ * simply sets up the security context for the user in order to
+ * properly complete the authentication processing.
+ *
+ * <P>If any groups have been assigned to cert-authenticated users
+ * through the assign-groups property these groups are added to
+ * the security context for the current user.
+ *
+ * @param subject The Subject object for the authentication request.
+ * @param x500name The X500Name object from the user certificate.
+ *
+ */
+ public void authenticate(Subject subject, X500Name x500name)
+ {
+ // It is important to use x500name.getName() in order to be
+ // consistent with web containers view of the name - see bug
+ // 4646134 for reasons why this matters.
+
+ String name = x500name.getName();
+
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.finest(
+ "Certificate realm setting up security context for: "+ name);
+ }
+
+ if (defaultGroups != null) {
+ Set<Principal> principalSet = subject.getPrincipals();
+ Enumeration<String> e = defaultGroups.elements();
+ while (e.hasMoreElements()) {
+ principalSet.add(new Group(e.nextElement()));
+ }
+ }
+ if (!subject.getPrincipals().isEmpty()) {
+ DistinguishedPrincipalCredential dpc = new DistinguishedPrincipalCredential(x500name);
+ subject.getPublicCredentials().add(dpc);
+ }
+
+ SecurityContext securityContext =
+ new SecurityContext(name, subject);
+
+ SecurityContext.setCurrent(securityContext);
+ /*AppServSecurityContext secContext = Util.getDefaultHabitat().getByContract(AppServSecurityContext.class);
+ AppServSecurityContext securityContext = secContext.newInstance(name, subject);
+ securityContext.setCurrentSecurityContext(securityContext);*/
+
+ }
+
+ /**
+ * <p> A <code>LoginModule</code> for <code>CertificateRealm</code>
+ * can instantiate and pass a <code>AppContextCallback</code>
+ * to <code>handle</code> method of the passed
+ * <code>CallbackHandler</code> to retrieve the application
+ * name information.
+ */
+ public final static class AppContextCallback implements Callback {
+ private String moduleID;
+
+ /**
+ * Get the fully qualified module name. The module name consists
+ * of the application name (if not a singleton) followed by a '#'
+ * and the name of the module.
+ *
+ * <p>
+ *
+ * @return the application name.
+ */
+ public String getModuleID() {
+ return moduleID;
+ }
+
+ /**
+ * Set the fully qualified module name. The module name consists
+ * of the application name (if not a singleton) followed by a '#'
+ * and the name of the module.
+ *
+ */
+ public void setModuleID(String moduleID) {
+ this.moduleID = moduleID;
+ }
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealm.java
new file mode 100644
index 0000000..ab4943c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealm.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.file;
+
+import java.util.*;
+import java.util.logging.Level;
+import java.io.*;
+import com.sun.enterprise.security.auth.realm.User;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.IASRealm;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.common.Util;
+import com.sun.enterprise.security.util.IASSecurityException;
+import org.glassfish.internal.api.RelativePathResolver;
+import org.glassfish.security.common.FileRealmHelper;
+import org.jvnet.hk2.annotations.Service;
+
+
+/**
+ * Realm wrapper for supporting file password authentication.
+ *
+ * <P>In addition to the basic realm functionality, this class provides
+ * administration methods for the file realm.
+ *
+ * <P>Format of the keyfile used by this class is one line per user
+ * containing <code>username;password;groups</code> where:
+ * <ul>
+ * <li>username - Name string.
+ * <li>password - A salted SHA hash (SSHA) of the user password.
+ * <li>groups - A comma separated list of group memberships.
+ * </ul>
+ *
+ * <P>The file realm needs the following properties in its configuration:
+ * <ul>
+ * <li>file - Full path to the keyfile to load
+ * <li>jaas-ctx - JAAS context name used to access LoginModule for
+ * authentication.
+ * </ul>
+ *
+ * @author Harry Singh
+ * @author Jyri Virkki
+ * @author Shing Wai Chan
+ */
+@Service
+public final class FileRealm extends IASRealm
+{
+ // Descriptive string of the authentication type of this realm.
+ public static final String AUTH_TYPE = "filepassword";
+
+ // These are property names which should be in auth-realm in server.xml
+ public static final String PARAM_KEYFILE="file";
+
+ FileRealmHelper helper;
+
+ /**
+ * Constructor.
+ *
+ * <P>The created FileRealm instance is not registered in the
+ * Realm registry. This constructor can be used by admin tools
+ * to create a FileRealm instance which can be edited by adding or
+ * removing users and then saved to disk, without affecting the
+ * installed realm instance.
+ *
+ * <P>The file provided should always exist. A default (empty) keyfile
+ * is installed with the server so this should always be the case
+ * unless the user has manually deleted this file. If this file
+ * path provided does not point to an existing file this constructor
+ * will first attempt to create it. If this succeeds the constructor
+ * returns normally and an empty keyfile will have been created; otherwise
+ * an exception is thrown.
+ *
+ * @param keyfile Full path to the keyfile to read for user data.
+ * @exception BadRealmException If the configuration parameters
+ * identify a corrupt realm.
+ * @exception NoSuchRealmException If the configuration parameters
+ * specify a realm which doesn't exist.
+ *
+ */
+ public FileRealm(String keyfile)
+ throws BadRealmException, NoSuchRealmException
+ {
+ Properties p = new Properties();
+ // The original keyfile is stored here for use in the init and refresh methods
+ p.setProperty(PARAM_KEYFILE, keyfile);
+ p.setProperty(IASRealm.JAAS_CONTEXT_PARAM, "ignore");
+ this.init(p);
+ }
+
+ /*
+ * No arg constructor used by the Realm class when creating realms.
+ * This is followed by a call to the init() method.
+ */
+ public FileRealm()
+ {
+ }
+
+ /**
+ * Return a list of the file names used by all file realms
+ * defined for the specified config.
+ *
+ * @param config the config object
+ * @return a list of the file names for all files realms in the
+ * config
+ */
+ public static List<String> getRealmFileNames(Config config) {
+ List<String> files = new ArrayList<String>();
+ SecurityService securityService = config.getSecurityService();
+ for (AuthRealm authRealm : securityService.getAuthRealm()) {
+ String fileRealmClassName = authRealm.getClassname();
+ // skip it if it's not a file realm
+ if (fileRealmClassName == null ||
+ !fileRealmClassName.equals(FileRealm.class.getName()))
+ continue;
+ String file = authRealm.getPropertyValue("file");
+ if (file == null) // skip if no "file" property
+ continue;
+ if (file.contains("$")) {
+ file = RelativePathResolver.resolvePath(file);
+ }
+ files.add(file);
+ }
+ return files;
+ }
+
+
+ /**
+ * Initialize a realm with some properties. This can be used
+ * when instantiating realms from their descriptions. This
+ * method is invoked from Realm during initialization.
+ *
+ * @param props Initialization parameters used by this realm.
+ * @exception BadRealmException If the configuration parameters
+ * identify a corrupt realm.
+ * @exception NoSuchRealmException If the configuration parameters
+ * specify a realm which doesn't exist.
+ *
+ */
+ @Override
+ protected void init(Properties props)
+ throws BadRealmException, NoSuchRealmException
+ {
+ super.init(props);
+ String file = props.getProperty(PARAM_KEYFILE);
+ if (file == null) {
+ String msg = sm.getString("filerealm.nofile");
+ throw new BadRealmException(msg);
+ }
+ if (file.contains("$")) {
+ file = RelativePathResolver.resolvePath(file);
+ }
+
+ this.setProperty(PARAM_KEYFILE, file);
+
+ String jaasCtx = props.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
+ if (jaasCtx == null) {
+ String msg = sm.getString("filerealm.nomodule");
+ throw new BadRealmException(msg);
+ }
+ this.setProperty(IASRealm.JAAS_CONTEXT_PARAM, jaasCtx);
+
+ _logger.log(Level.FINE, "FileRealm : "+ PARAM_KEYFILE + "={0}", file);
+ _logger.log(Level.FINE, "FileRealm : "+ IASRealm.JAAS_CONTEXT_PARAM + "={0}", jaasCtx);
+ try {
+ if (Util.isEmbeddedServer()) {
+ String embeddedFilePath = Util.writeConfigFileToTempDir(file).getAbsolutePath();
+ file = embeddedFilePath;
+ }
+ helper = new FileRealmHelper(file);
+ } catch (IOException ioe) {
+ String msg = sm.getString("filerealm.noaccess", ioe.toString());
+ throw new BadRealmException(msg);
+ }
+ }
+
+
+ /**
+ * Returns a short (preferably less than fifteen characters) description
+ * of the kind of authentication which is supported by this realm.
+ *
+ * @return Description of the kind of authentication that is directly
+ * supported by this realm.
+ */
+ @Override
+ public String getAuthType()
+ {
+ return AUTH_TYPE;
+ }
+
+
+ /**
+ * Returns names of all the users in this particular realm.
+ *
+ * @return enumeration of user names (strings)
+ * @exception BadRealmException if realm data structures are bad
+ */
+ @Override
+ public Enumeration<String> getUserNames()
+ throws BadRealmException
+ {
+ return Collections.enumeration(helper.getUserNames());
+ }
+
+
+ /**
+ * Returns the information recorded about a particular named user.
+ *
+ * @param name Name of the user whose information is desired.
+ * @return The user object.
+ * @exception NoSuchUserException if the user doesn't exist.
+ * @exception BadRealmException if realm data structures are bad.
+ */
+ @Override
+ public User getUser(String name)
+ throws NoSuchUserException
+ {
+
+ FileRealmHelper.User u = helper.getUser(name);
+ if (u == null) {
+ String msg = sm.getString("filerealm.nouser", name);
+ throw new NoSuchUserException(msg);
+ }
+ return new FileRealmUser(u, null);
+ }
+
+
+ /**
+ * Returns names of all the groups in this particular realm.
+ * Note that this will not return assign-groups.
+ *
+ * @return enumeration of group names (strings)
+ * @exception BadRealmException if realm data structures are bad
+ */
+ @Override
+ public Enumeration getGroupNames()
+ throws BadRealmException
+ {
+ return Collections.enumeration(helper.getGroupNames());
+ }
+
+
+ /**
+ * Returns the name of all the groups that this user belongs to.
+ * @param username Name of the user in this realm whose group listing
+ * is needed.
+ * @return Enumeration of group names (strings).
+ * @exception InvalidOperationException thrown if the realm does not
+ * support this operation - e.g. Certificate realm does not support
+ * this operation.
+ */
+ @Override
+ public Enumeration getGroupNames(String username)
+ throws NoSuchUserException
+ {
+ String groups[] = helper.getGroupNames(username);
+ if ( groups == null ) {
+ groups = new String[]{};
+ }
+ groups = addAssignGroups(groups);
+ return Collections.enumeration(Arrays.asList(groups));
+ }
+
+ /**
+ * Refreshes the realm data so that new users/groups are visible.
+ *
+ * <P>A new FileRealm instance is created and initialized from the
+ * keyfile on disk. The new instance is installed in the Realm registry
+ * so future Realm.getInstance() calls will obtain the new data. Any
+ * existing references to this instance (e.g. in active LoginModule
+ * sessions) are unaffected.
+ *
+ * @exception BadRealmException if realm data structures are bad
+ *
+ */
+ @Override
+ public void refresh()
+ throws BadRealmException
+ {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("Reloading file realm data.");
+ }
+
+ try {
+ FileRealm newRealm = new FileRealm(getProperty(PARAM_KEYFILE));
+ newRealm.init(getProperties());
+ Realm.updateInstance(newRealm, this.getName());
+ } catch (Exception e) {
+ throw new BadRealmException(e.toString());
+ }
+ }
+
+ /**
+ * Refreshes the realm data so that new users/groups are visible.
+ *
+ * <P>A new FileRealm instance is created and initialized from the
+ * keyfile on disk. The new instance is installed in the Realm registry
+ * so future Realm.getInstance() calls will obtain the new data. Any
+ * existing references to this instance (e.g. in active LoginModule
+ * sessions) are unaffected.
+ * @param config
+ * @exception BadRealmException if realm data structures are bad
+ *
+ */
+ @Override
+ public void refresh(String configName)
+ throws BadRealmException {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("Reloading file realm data.");
+ }
+
+ try {
+ FileRealm newRealm = new FileRealm(getProperty(PARAM_KEYFILE));
+ newRealm.init(getProperties());
+ Realm.updateInstance(configName, newRealm, this.getName());
+ } catch (Exception e) {
+ throw new BadRealmException(e.toString());
+ }
+ }
+
+ /**
+ * Adds new user to file realm. User cannot exist already.
+ *
+ * @param name User name.
+ * @param password Cleartext password for the user.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ *
+ */
+ @Override
+ public void addUser(String name, char[] password, String[] groupList)
+ throws BadRealmException, IASSecurityException {
+ helper.addUser(name, password, groupList);
+ }
+
+ /**
+ * Remove user from file realm. User must exist.
+ *
+ * @param name User name.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ @Override
+ public void removeUser(String name)
+ throws NoSuchUserException, BadRealmException {
+ helper.removeUser(name);
+ }
+
+ /**
+ * Update data for an existing user. User must exist.
+ *
+ * @param name Current name of the user to update.
+ * @param newName New name to give this user. It can be the same as
+ * the original name. Otherwise it must be a new user name which
+ * does not already exist as a user.
+ * @param password Cleartext password for the user. If non-null the user
+ * password is changed to this value. If null, the original password
+ * is retained.
+ * @param groupList List of groups to which user belongs.
+ * @throws BadRealmException If there are problems adding user.
+ * @throws NoSuchUserException If user does not exist.
+ *
+ */
+ @Override
+ public void updateUser(String name, String newName, char[] password,
+ String[] groups)
+ throws NoSuchUserException, BadRealmException,
+ IASSecurityException {
+ helper.updateUser(name, newName, password, groups);
+ }
+
+
+ /**
+ * Authenticates a user.
+ *
+ * <P>This method is invoked by the FileLoginModule in order to
+ * authenticate a user in the file realm. The authentication decision
+ * is kept within the realm class implementation in order to keep
+ * the password cache in a single location with no public accessors,
+ * to simplify future improvements.
+ *
+ * @param user Name of user to authenticate.
+ * @param password Password provided by client.
+ * @returns Array of group names the user belongs to, or null if
+ * authentication fails.
+ * @throws LoginException If there are errors during authentication.
+ *
+ */
+ public String[] authenticate(String user, char[] password)
+ {
+ String groups[] = helper.authenticate(user, password);
+ if (groups != null) {
+ groups = addAssignGroups(groups);
+ }
+ return groups;
+ }
+
+ /*
+ * Test whether their is a user in the FileRealm that has a password that
+ * has been set, i.e., something other than the resetKey.
+ */
+ public boolean hasAuthenticatableUser()
+ {
+ return helper.hasAuthenticatableUser();
+ }
+
+ /**
+ * @return true if the realm implementation support User Management (add,remove,update user)
+ */
+ @Override
+ public boolean supportsUserManagement() {
+ //File Realm supports UserManagement
+ return true;
+ }
+
+ /**
+ * Persist the realm data to permanent storage
+ * @throws com.sun.enterprise.security.auth.realm.BadRealmException
+ */
+ @Override
+ public void persist() throws BadRealmException {
+ try {
+ helper.persist();
+ } catch (IOException ex) {
+ throw new BadRealmException(ex);
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealmUser.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealmUser.java
new file mode 100644
index 0000000..c367e41
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/file/FileRealmUser.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.file;
+
+import java.util.*;
+
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.realm.User;
+import org.glassfish.security.common.FileRealmHelper;
+
+
+/**
+ * Represents a FileRealm user.
+ *
+ *
+ */
+public class FileRealmUser implements User
+{
+ FileRealmHelper.User user;
+ Hashtable attributes = new Hashtable();
+ String realm;
+ /**
+ * Constructor.
+ *
+ */
+ public FileRealmUser(FileRealmHelper.User user, String realm)
+ {
+ this.user = user;
+ this.realm = realm;
+ }
+
+ public String[] getGroups() {
+ return user.getGroups();
+ }
+
+ /**
+ * Returns the realm with which this user is associated
+ *
+ * @return Realm name.
+ * @exception NoSuchRealmException if the realm associated this user
+ * no longer exist
+ *
+ */
+ @Override
+ public Realm getRealm() throws NoSuchRealmException
+ {
+ return Realm.getInstance(realm);
+ }
+
+ /**
+ * Return the requested attribute for the user.
+ * <P>Not really needed.
+ *
+ * @param key string identifies the attribute.
+ */
+ @Override
+ public Object getAttribute (String key)
+ {
+ return attributes.get(key);
+ }
+
+ /**
+ * Return the names of the supported attributes for this user.
+ * <P>Not really needed.
+ */
+ @Override
+ public Enumeration getAttributeNames () {
+ return attributes.keys();
+ }
+
+ @Override
+ public String getName() {
+ return user.getName();
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/jdbc/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/jdbc/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/jdbc/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/CustomSocketFactory.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/CustomSocketFactory.java
new file mode 100644
index 0000000..04c4a43
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/CustomSocketFactory.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.ldap;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.SecurityServicesUtil;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import com.sun.enterprise.util.i18n.StringManager;
+import java.io.IOException;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.Comparator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import java.net.InetAddress;
+
+import org.glassfish.internal.api.Globals;
+import org.glassfish.internal.api.SharedSecureRandom;
+/**
+ * Custom socket factory for ldaps (SSL).
+ *
+ * The comparator only works in JDK 1.6 onwards. Due to a bug in JDK 1.6
+ * compare method invocation fails with a classcast exception. The caller is
+ * trying to pass java.lang.String when it should have passed
+ * javax.net.SocketFactory
+ *
+ * @see com.sun.enterprise.security.auth.realm.ldap.LDAPRealm
+ *
+ */
+public class CustomSocketFactory extends SocketFactory implements Comparator<SocketFactory> {
+ private SocketFactory socketFactory;
+
+ public static final String SSL = "SSL";
+ protected static final Logger _logger =
+ SecurityLoggerInfo.getLogger();
+ protected static final StringManager sm =
+ StringManager.getManager(CustomSocketFactory.class);
+ private static final CustomSocketFactory customSocketFactory = new CustomSocketFactory();
+
+ public CustomSocketFactory() {
+ SSLUtils sslUtils = Globals.getDefaultHabitat().getService(SSLUtils.class);
+ SSLContext sc = null;
+ try {
+ sc = SSLContext.getInstance(SSL);
+ sc.init(sslUtils.getKeyManagers(), sslUtils.getTrustManagers(), SharedSecureRandom.get());
+ socketFactory = sc.getSocketFactory();
+ } catch (Exception ex) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.securityExceptionError, ex);
+ }
+ }
+
+ /**
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
+ */
+ public Socket createSocket(String arg0, int arg1) throws IOException,
+ UnknownHostException {
+ return socketFactory.createSocket(arg0, arg1);
+ }
+
+ /**
+ * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int)
+ */
+ public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
+ return socketFactory.createSocket(arg0, arg1);
+ }
+
+ /**
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int,
+ * java.net.InetAddress, int)
+ */
+ public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3)
+ throws IOException, UnknownHostException {
+ return socketFactory.createSocket(arg0, arg1, arg2, arg3);
+ }
+
+ /**
+ * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int,
+ * java.net.InetAddress, int)
+ */
+ public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2,
+ int arg3) throws IOException {
+ return socketFactory.createSocket(arg0, arg1, arg2, arg3);
+ }
+
+ public int compare(SocketFactory s1, SocketFactory s2) {
+ return s1.getClass().toString().compareTo(s2.getClass().toString());
+ }
+
+ public static SocketFactory getDefault() {
+ return customSocketFactory;
+ }
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/LDAPRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/LDAPRealm.java
new file mode 100644
index 0000000..d49eef9
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/ldap/LDAPRealm.java
@@ -0,0 +1,769 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.ldap;
+
+import java.util.*;
+import java.io.IOException;
+import java.util.logging.Level;
+import javax.naming.CompositeName;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.security.auth.login.LoginException;
+import java.security.Principal;
+// imported from the ldap booster pack
+import com.sun.jndi.ldap.obj.GroupOfURLs;
+import javax.security.auth.x500.X500Principal;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.InvalidOperationException;
+
+import com.sun.enterprise.security.auth.realm.IASRealm;
+import java.lang.StringBuffer;
+import java.util.regex.Matcher;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import org.glassfish.internal.api.RelativePathResolver;
+import org.jvnet.hk2.annotations.Service;
+import sun.security.x509.X500Name;
+
+
+/**
+ * Realm wrapper for supporting LDAP authentication.
+ *
+ * <P>See LDAPLoginModule documentation for more details on the operation
+ * of the LDAP realm and login module.
+ *
+ * <P>The ldap realm needs the following properties in its configuration:
+ * <ul>
+ * <li>directory - URL of LDAP directory to use
+ * <li>base-dn - The base DN to use for user searches.
+ * <li>jaas-ctx - JAAS context name used to access LoginModule for
+ * authentication.
+ * </ul>
+ *
+ * <P>Besides JDK Context properties start with java.naming, javax.security,
+ * one can also set connection pool related properties starting with
+ * com.sun.jndi.ldap.connect.pool.
+ * See http://java.sun.com/products/jndi/tutorial/ldap/connect/config.html
+ * for details.
+ * Also, the following optional attributes can also be specified:
+ * <ul>
+ * <li>search-filter - LDAP filter to use for searching for the user
+ * entry based on username given to iAS. The default value is
+ * <code>uid=%s</code> where %s is expanded to the username.
+ * <li>group-base-dn - The base DN to use for group searches. By default
+ * its value is the same as base-dn.
+ * <li>group-search-filter - The LDAP filter to use for searching group
+ * membership of a given user. The default value is <code>
+ * uniquemember=%d</code> where %d is expanded to the DN of the
+ * user found by the user search.
+ * <li>group-target - The attribute which value(s) are interpreted as
+ * group membership names of the user. Default value is <code>cn</code>.
+ * <li>search-bind-dn - The dn of ldap user. optional and no default value.
+ * <li>search-bind-password - The password of search-bind-dn.optional and
+ * no default value.
+ * <li>pool-size - The JNDI ldap connection pool size.
+ * </ul>
+ *
+ * @see com.sun.enterprise.security.auth.login.LDAPLoginModule
+ *
+ */
+@Service
+public final class LDAPRealm extends IASRealm
+{
+ // Descriptive string of the authentication type of this realm.
+ public static final String AUTH_TYPE = "ldap";
+
+ // These are property names which should be in auth-realm in server.xml
+ public static final String PARAM_DIRURL="directory";
+ public static final String PARAM_USERDN="base-dn";
+
+ // These are optional, defaults are provided
+ // %s = subject name
+ // %d = DN of user search result
+ public static final String PARAM_SEARCH_FILTER="search-filter";
+ public static final String PARAM_GRPDN="group-base-dn";
+ public static final String PARAM_GRP_SEARCH_FILTER="group-search-filter";
+ public static final String PARAM_GRP_TARGET="group-target";
+ public static final String PARAM_DYNAMIC_GRP_FILTER="dynamic-group-search-filter";
+ public static final String PARAM_DYNAMIC_GRP_TARGET="dynamic-group-target";
+ public static final String PARAM_MODE="mode";
+ public static final String PARAM_JNDICF="jndiCtxFactory";
+ public static final String PARAM_POOLSIZE="pool-size";
+
+ // These are optional, no default values are provided
+ public static final String PARAM_BINDDN="search-bind-dn";
+ public static final String PARAM_BINDPWD="search-bind-password";
+
+ // Only find-bind mode is supported so mode attribute is not exposed yet
+ public static final String MODE_FIND_BIND="find-bind";
+
+ // Expansion strings
+ public static final String SUBST_SUBJECT_NAME="%s";
+ public static final String SUBST_SUBJECT_DN="%d";
+
+ // Defaults
+ private static final String SEARCH_FILTER_DEFAULT=
+ "uid="+SUBST_SUBJECT_NAME;
+ private static final String GRP_SEARCH_FILTER_DEFAULT=
+ "uniquemember="+SUBST_SUBJECT_DN;
+ private static final String GRP_TARGET_DEFAULT="cn";
+ private static final String DYNAMIC_GRP_TARGET_DEFAULT="ismemberof";//"memberOf";
+ private static final String MODE_DEFAULT=MODE_FIND_BIND;
+ private static final String JNDICF_DEFAULT=
+ "com.sun.jndi.ldap.LdapCtxFactory";
+ private static final int POOLSIZE_DEFAULT=5;
+
+ private final String[] _dnOnly = {"dn"};
+
+ private static final String SUN_JNDI_POOL = "com.sun.jndi.ldap.connect.pool";
+ private static final String SUN_JNDI_POOL_ = "com.sun.jndi.ldap.connect.pool.";
+ private static final String SUN_JNDI_POOL_PROTOCOL = "com.sun.jndi.ldap.connect.pool.protocol";
+ private static final String SUN_JNDI_POOL_MAXSIZE = "com.sun.jndi.ldap.connect.pool.maxsize";
+ // dynamic group related properties.
+ private static final String DYNAMIC_GROUP_OBJECT_FACTORY =
+ "com.sun.jndi.ldap.obj.LdapGroupFactory";
+ public static final String DYNAMIC_GROUP_FACTORY_OBJECT_PROPERTY =
+ "java.naming.factory.object";
+ private static final String DYNAMIC_GROUP_STATE_FACTORY =
+ "com.sun.jndi.ldap.obj.LdapGroupFactory";
+ public static final String DYNAMIC_GROUP_STATE_FACTORY_PROPERTY =
+ "java.naming.factory.state";
+ public static final String LDAP_SOCKET_FACTORY = "java.naming.ldap.factory.socket";
+ public static final String DEFAULT_SSL_LDAP_SOCKET_FACTORY = "com.sun.enterprise.security.auth.realm.ldap.CustomSocketFactory";
+ public static final String LDAPS_URL = "ldaps://";
+ public static final String DEFAULT_POOL_PROTOCOL = "plain ssl";
+
+ public static final String DYNAMIC_GROUP_FILTER =
+ "(&(objectclass=groupofuniquenames)(objectclass=*groupofurls*))";
+
+ public static final String SSL = "SSL";
+
+ private HashMap groupCache;
+ private Vector emptyVector;
+ private Properties ldapBindProps = new Properties();
+
+ /**
+ * Initialize a realm with some properties. This can be used
+ * when instantiating realms from their descriptions. This
+ * method may only be called a single time.
+ *
+ * @param props Initialization parameters used by this realm.
+ * @exception BadRealmException If the configuration parameters
+ * identify a corrupt realm.
+ * @exception NoSuchRealmException If the configuration parameters
+ * specify a realm which doesn't exist.
+ *
+ */
+ public synchronized void init(Properties props)
+ throws BadRealmException, NoSuchRealmException
+ {
+ super.init(props);
+ String url = props.getProperty(PARAM_DIRURL);
+ String dn = props.getProperty(PARAM_USERDN);
+ String jaasCtx = props.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
+
+ if (url==null || dn==null || jaasCtx==null) {
+ String msg = sm.getString("ldaprealm.badconfig", url, dn, jaasCtx);
+ throw new BadRealmException(msg);
+ }
+ this.setProperty(PARAM_DIRURL, url);
+ ldapBindProps.setProperty(Context.PROVIDER_URL, url);
+ this.setProperty(PARAM_USERDN, dn);
+ this.setProperty(IASRealm.JAAS_CONTEXT_PARAM, jaasCtx);
+
+ String mode = props.getProperty(PARAM_MODE, MODE_DEFAULT);
+ if (!MODE_DEFAULT.equals(mode)) {
+ String msg = sm.getString("ldaprealm.badmode", mode);
+ throw new BadRealmException(msg);
+ }
+ this.setProperty(PARAM_MODE, mode);
+
+ String ctxF = props.getProperty(PARAM_JNDICF, JNDICF_DEFAULT);
+ this.setProperty(PARAM_JNDICF, ctxF);
+ ldapBindProps.setProperty(Context.INITIAL_CONTEXT_FACTORY, ctxF);
+
+ String searchFilter = props.getProperty(
+ PARAM_SEARCH_FILTER, SEARCH_FILTER_DEFAULT);
+ this.setProperty(PARAM_SEARCH_FILTER,searchFilter);
+
+ String grpDN = props.getProperty(PARAM_GRPDN, dn);
+ this.setProperty(PARAM_GRPDN, grpDN);
+
+ String grpSearchFilter = props.getProperty(
+ PARAM_GRP_SEARCH_FILTER, GRP_SEARCH_FILTER_DEFAULT);
+ this.setProperty(PARAM_GRP_SEARCH_FILTER, grpSearchFilter);
+
+ String dynGrpSearchFilter = props.getProperty(
+ PARAM_DYNAMIC_GRP_FILTER, SEARCH_FILTER_DEFAULT);
+ this.setProperty(PARAM_DYNAMIC_GRP_FILTER, dynGrpSearchFilter);
+
+ String grpTarget = props.getProperty(
+ PARAM_GRP_TARGET, GRP_TARGET_DEFAULT);
+ this.setProperty(PARAM_GRP_TARGET, grpTarget);
+
+ String dynGrpTarget = props.getProperty(
+ PARAM_DYNAMIC_GRP_TARGET, DYNAMIC_GRP_TARGET_DEFAULT);
+ this.setProperty(PARAM_DYNAMIC_GRP_TARGET, dynGrpTarget);
+
+ String objectFactory = props.getProperty(
+ DYNAMIC_GROUP_FACTORY_OBJECT_PROPERTY, DYNAMIC_GROUP_OBJECT_FACTORY);
+ this.setProperty(DYNAMIC_GROUP_FACTORY_OBJECT_PROPERTY, objectFactory);
+ ldapBindProps.setProperty(DYNAMIC_GROUP_FACTORY_OBJECT_PROPERTY, objectFactory);
+
+ String stateFactory = props.getProperty(
+ DYNAMIC_GROUP_STATE_FACTORY_PROPERTY, DYNAMIC_GROUP_STATE_FACTORY);
+ this.setProperty(DYNAMIC_GROUP_STATE_FACTORY_PROPERTY, stateFactory);
+ ldapBindProps.setProperty(DYNAMIC_GROUP_STATE_FACTORY_PROPERTY, stateFactory);
+
+ String bindDN = props.getProperty(PARAM_BINDDN);
+ if (bindDN != null) {
+ this.setProperty(PARAM_BINDDN, bindDN);
+ ldapBindProps.setProperty(Context.SECURITY_PRINCIPAL, bindDN);
+ }
+ String bindPWD = props.getProperty(PARAM_BINDPWD);
+ if (bindPWD != null) {
+ //If the passwors is aliased, de-alias it
+ try {
+ bindPWD = RelativePathResolver.getRealPasswordFromAlias(bindPWD);
+ }catch(Exception ex) {
+ _logger.log(Level.WARNING, "ldaprealm.pwd.dealiasing.failed",ex);
+ }
+ this.setProperty(PARAM_BINDPWD, bindPWD);
+ ldapBindProps.setProperty(Context.SECURITY_CREDENTIALS, bindPWD);
+ }
+
+ Enumeration penum = props.propertyNames();
+ while (penum.hasMoreElements()) {
+ String propName = (String)penum.nextElement();
+ if (propName.startsWith("java.naming.") ||
+ propName.startsWith("javax.security.") ||
+ propName.startsWith("com.sun.jndi.ldap.")) {
+ ldapBindProps.setProperty(propName, props.getProperty(propName));
+ } else if (propName.startsWith(SUN_JNDI_POOL_) &&
+ !SUN_JNDI_POOL_MAXSIZE.equals(propName)) {
+ if (System.getProperty(propName) == null) {
+ System.setProperty(propName, props.getProperty(propName));
+ }
+ }
+ }
+
+ String poolSize =
+ Integer.getInteger(PARAM_POOLSIZE,POOLSIZE_DEFAULT).toString();
+ String sunPoolSizeStr = props.getProperty(SUN_JNDI_POOL_MAXSIZE,
+ poolSize);
+ //Precedence rule: SUN_JNDI_POOL_MAXSIZE > PARAM_POOLSIZE > POOLSIZE_DEFAULT
+ try {
+ sunPoolSizeStr = Integer.valueOf(sunPoolSizeStr).toString();
+ } catch(Exception ex) {
+ sunPoolSizeStr = poolSize;
+ }
+ if (System.getProperty(SUN_JNDI_POOL_MAXSIZE) == null) {
+ System.setProperty(SUN_JNDI_POOL_MAXSIZE, sunPoolSizeStr);
+ }
+ this.setProperty(PARAM_POOLSIZE, sunPoolSizeStr);
+
+ String usePool = props.getProperty(SUN_JNDI_POOL, "true");
+ ldapBindProps.setProperty(SUN_JNDI_POOL, usePool);
+
+ if( url.startsWith(LDAPS_URL)) {
+ ldapBindProps.setProperty(LDAP_SOCKET_FACTORY,
+ DEFAULT_SSL_LDAP_SOCKET_FACTORY);
+ if (System.getProperty(SUN_JNDI_POOL_PROTOCOL) == null) {
+ System.setProperty(SUN_JNDI_POOL_PROTOCOL,DEFAULT_POOL_PROTOCOL);
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "LDAPRealm : Using custom socket factory for SSL with pooling");
+ }
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ Properties tempProps = (Properties)ldapBindProps.clone();
+ tempProps.remove(Context.SECURITY_CREDENTIALS);
+ _logger.log(Level.FINE, "LDAPRealm : " + tempProps);
+ }
+
+ groupCache = new HashMap();
+ emptyVector = new Vector();
+ }
+
+
+ /**
+ * Returns a short (preferably less than fifteen characters) description
+ * of the kind of authentication which is supported by this realm.
+ *
+ * @return Description of the kind of authentication that is directly
+ * supported by this realm.
+ */
+ public String getAuthType()
+ {
+ return AUTH_TYPE;
+ }
+
+ private String[] addMappedGroupNames(String[] grpList) {
+
+ if (groupMapper == null) {
+ return grpList;
+ }
+ ArrayList<String> finalresult = new ArrayList<String>();
+ for (String grp : grpList) {
+ ArrayList<String> result = new ArrayList<String>();
+ groupMapper.getMappedGroups(grp, result);
+ finalresult.add(grp);
+ if (!result.isEmpty()) {
+ finalresult.addAll(result);
+ }
+ }
+ return finalresult.toArray(new String[finalresult.size()]);
+ }
+
+ /**
+ * Get binding properties defined in server.xml for LDAP server.
+ *
+ */
+ private Properties getLdapBindProps()
+ {
+ return (Properties)ldapBindProps.clone();
+ }
+
+
+ private List<String> getGroups(String userDN) {
+ //no authentication has happened through the realm.
+ DirContext ctx = null;
+ String srcFilter = null;
+
+ String dynFilter = null;
+ String dynMember = getProperty(PARAM_DYNAMIC_GRP_TARGET);
+ try {
+ ctx = new InitialDirContext(getLdapBindProps());
+
+ String _username = userDN;
+ try {
+ X500Name name = new X500Name(userDN);
+ _username = name.getCommonName();
+ } catch (IOException e) {
+ //Ignoring the exception to suppot simple group names as userDN
+ //Issue GLASSFISH-19595
+ }
+ if (_username == null && userDN != null && userDN.startsWith("uid")) {
+ //handle uid=XXX here where cn is not present
+ //TODO :maybe there is a better way to handle this??
+ int first = userDN.indexOf("uid=");
+ int last = userDN.indexOf(",");
+ if (first != -1 && last != -1) {
+ _username = userDN.substring(first + 4, last);
+ }
+
+ }
+ StringBuffer sb = new StringBuffer(getProperty(PARAM_GRP_SEARCH_FILTER));
+ StringBuffer dynSb = new StringBuffer(getProperty(PARAM_DYNAMIC_GRP_FILTER));
+ substitute(sb, SUBST_SUBJECT_NAME, _username);
+ substitute(sb, SUBST_SUBJECT_DN, userDN);
+ substitute(dynSb, SUBST_SUBJECT_NAME, _username);
+ substitute(dynSb, SUBST_SUBJECT_DN, userDN);
+
+ srcFilter = sb.toString();
+ dynFilter = dynSb.toString();
+ List<String> groupsList = new ArrayList<String>();
+ groupsList.addAll(groupSearch(ctx, getProperty(PARAM_GRPDN), srcFilter, getProperty(PARAM_GRP_TARGET)));
+ // search filter is constructed internally as
+ // as a groupofURLS
+ groupsList.addAll(dynamicGroupSearch(ctx, getProperty(PARAM_GRPDN), dynMember,
+ dynFilter, getProperty(PARAM_GRP_TARGET)));
+ return groupsList;
+ } catch (Exception e) {
+ _logger.log(Level.WARNING, "ldaprealm.groupsearcherror",e);
+ } finally {
+ if (ctx != null) {
+ try {
+ ctx.close();
+ } catch (NamingException e) {
+ _logger.log(Level.WARNING, "ldaprealm.exception", e);
+ }
+ }
+ }
+ return null;
+ }
+ /**
+ * Returns the name of all the groups that this user belongs to.
+ * Note that this information is only known after the user has
+ * logged in. This is called from web path role verification, though
+ * it should not be.
+ *
+ * @param username Name of the user in this realm whose group listing
+ * is needed.
+ * @return Enumeration of group names (strings).
+ * @exception InvalidOperationException thrown if the realm does not
+ * support this operation - e.g. Certificate realm does not support
+ * this operation.
+ */
+ public Enumeration getGroupNames (String username)
+ throws InvalidOperationException, NoSuchUserException
+ {
+ Vector v = (Vector)groupCache.get(username);
+ if (v == null) {
+ //Note : assuming the username is a userDN here
+ List<String> searchedGrps = getGroups(username);
+ if (searchedGrps != null) {
+ return Collections.enumeration(searchedGrps);
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "No groups available for: "+username);
+ }
+ // we don't load group here as we need to bind ctx to user with
+ // password before doing that and password is not available here
+ return emptyVector.elements();
+ } else {
+ if (groupMapper != null) {
+ Vector ret = new Vector();
+ ret.addAll(v);
+ ArrayList<String> result = new ArrayList<String>();
+ for (Object o : v) {
+ String grp = (String)o;
+ ArrayList<String> tmp =this.getMappedGroupNames(grp);
+ result.addAll(tmp);
+ }
+ ret.addAll(result);
+ return ret.elements();
+ } else {
+ return v.elements();
+ }
+ }
+ }
+
+
+ /**
+ * Set group membership info for a user.
+ *
+ * <P>See bugs 4646133,4646270 on why this is here.
+ *
+ */
+ private void setGroupNames(String username, String[] groups)
+ {
+ Vector v = new Vector(groups.length);
+ for (int i=0; i<groups.length; i++) {
+ v.add(groups[i]);
+ }
+ groupCache.put(username, v);
+ }
+
+ /**
+ * Supports mode=find-bind. See class documentation.
+ *
+ */
+ public String[] findAndBind(String _username, char[] _password)
+ throws LoginException
+ {
+ // do search for user, substituting %s for username
+ _username = RFC2254Encode(_username);
+ StringBuffer sb = new StringBuffer(getProperty(PARAM_SEARCH_FILTER));
+ substitute(sb, SUBST_SUBJECT_NAME, _username);
+ String userid = sb.toString();
+
+ // attempt to bind as the user
+ DirContext ctx = null;
+ String srcFilter = null;
+ String[] grpList = null;
+
+ String dynFilter = null;
+ String dynMember = getProperty(PARAM_DYNAMIC_GRP_TARGET);
+ try {
+ ctx = new InitialDirContext(getLdapBindProps());
+ String realUserDN = userSearch(ctx, getProperty(PARAM_USERDN), userid);
+ if (realUserDN == null) {
+ String msg = sm.getString("ldaprealm.usernotfound", _username);
+ throw new LoginException(msg);
+ }
+
+ boolean bindSuccessful = bindAsUser(realUserDN, _password);
+ if (bindSuccessful == false) {
+ String msg = sm.getString("ldaprealm.bindfailed", realUserDN);
+ throw new LoginException(msg);
+ }
+
+ // search groups using above connection, substituting %d (and %s)
+ sb = new StringBuffer(getProperty(PARAM_GRP_SEARCH_FILTER));
+ StringBuffer dynSb = new StringBuffer(getProperty(PARAM_DYNAMIC_GRP_FILTER));
+
+ substitute(sb, SUBST_SUBJECT_NAME, _username);
+ substitute(sb, SUBST_SUBJECT_DN, realUserDN);
+ substitute(dynSb, SUBST_SUBJECT_NAME, _username);
+ substitute(dynSb, SUBST_SUBJECT_DN, realUserDN);
+
+ srcFilter = sb.toString();
+ dynFilter = dynSb.toString();
+ ArrayList groupsList = new ArrayList();
+ groupsList.addAll(groupSearch(ctx, getProperty(PARAM_GRPDN), srcFilter, getProperty(PARAM_GRP_TARGET)));
+ // search filter is constructed internally as
+ // as a groupofURLS
+ groupsList.addAll(dynamicGroupSearch(ctx, getProperty(PARAM_GRPDN), dynMember,
+ dynFilter, getProperty(PARAM_GRP_TARGET)));
+ grpList = new String[groupsList.size()];
+ groupsList.toArray(grpList);
+ } catch (Exception e) {
+ LoginException le=new LoginException(e.toString());
+ le.initCause(e);
+ _logger.log(Level.SEVERE, "ldaprealm.exception", le);
+ throw le;
+ } finally {
+ if (ctx != null) {
+ try {
+ ctx.close();
+ } catch (NamingException e) {}
+ }
+ }
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "LDAP:Group search filter: " + srcFilter);
+ StringBuffer gb = new StringBuffer();
+ gb.append("Group memberships found: ");
+ if (grpList.length > 0) {
+ for (int i=0; i<grpList.length; i++) {
+ gb.append(" "+grpList[i]);
+ }
+ } else {
+ gb.append("(null)");
+ }
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "LDAP: "+ gb.toString());
+ }
+ }
+ grpList = addAssignGroups(grpList);
+ grpList = this.addMappedGroupNames(grpList);
+ setGroupNames(_username, grpList);
+
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "LDAP: login succeeded for: " + _username);
+ }
+
+ return grpList;
+ }
+
+ /**
+ * Do anonymous search for the user. Should be unique if exists.
+ *
+ */
+ private String userSearch(DirContext ctx, String baseDN, String filter)
+ {
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINE, "search: baseDN: "+ baseDN +
+ " filter: " + filter);
+ }
+
+ String foundDN = null;
+ NamingEnumeration namingEnum = null;
+
+ SearchControls ctls = new SearchControls();
+ ctls.setReturningAttributes(_dnOnly);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ ctls.setCountLimit(1);
+
+ try {
+ namingEnum = ctx.search(baseDN, filter, ctls);
+ if (namingEnum.hasMore()) {
+ SearchResult res = (SearchResult)namingEnum.next();
+
+ StringBuffer sb = new StringBuffer();
+ //for dn name with '/'
+ CompositeName compDN = new CompositeName(res.getName());
+ String ldapDN = compDN.get(0);
+ sb.append(ldapDN);
+
+ if (res.isRelative()) {
+ sb.append(",");
+ sb.append(baseDN);
+ }
+ foundDN = sb.toString();
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINE, "Found user DN: " + foundDN);
+ }
+ }
+ } catch (Exception e) {
+ _logger.log(Level.WARNING, "ldaprealm.searcherror", filter);
+ _logger.log(Level.WARNING, "security.exception", e);
+ } finally {
+ if (namingEnum != null) {
+ try {
+ namingEnum.close();
+ } catch(Exception ex) {
+ }
+ }
+ }
+
+ return foundDN;
+ }
+
+ /**
+ * Attempt to bind as a specific DN.
+ *
+ */
+ private boolean bindAsUser(String bindDN, char[] password)
+ {
+ boolean bindSuccessful=false;
+
+ Properties p = getLdapBindProps();
+
+ p.put(Context.SECURITY_PRINCIPAL, bindDN);
+ p.put(Context.SECURITY_CREDENTIALS, new String(password));
+
+ DirContext ctx = null;
+ try {
+ ctx = new InitialDirContext(p);
+ bindSuccessful = true;
+ } catch (Exception e) {
+ if (_logger.isLoggable(Level.FINEST)) {
+ _logger.finest("Error binding to directory as: " + bindDN);
+ _logger.finest("Exception from JNDI: " + e.toString());
+ }
+ } finally {
+ if (ctx != null) {
+ try {
+ ctx.close();
+ } catch (NamingException e) {}
+ }
+ }
+ return bindSuccessful;
+ }
+
+ /**
+ * Search for group membership using the given connection.
+ *
+ */
+ private List dynamicGroupSearch(DirContext ctx, String baseDN,
+ String memberOfAttr, String filter, String target) throws NamingException
+ {
+ List groupList = new ArrayList();
+
+ String[] targets = new String[] { memberOfAttr };
+
+ try {
+ SearchControls ctls = new SearchControls();
+ ctls.setReturningAttributes(targets);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ //Set this to false to avoid objects and hence exposing ldap object
+ //injection.
+ ctls.setReturningObjFlag(false);
+
+ NamingEnumeration e = ctx.search(baseDN, filter, ctls);
+
+ while(e.hasMore()) {
+ SearchResult res = (SearchResult)e.next();
+ Attribute isMemberOf = res.getAttributes().get(memberOfAttr);
+ if (isMemberOf != null) {
+ for (Enumeration values = isMemberOf.getAll();
+ values.hasMoreElements();) {
+ String groupDN = (String) values.nextElement();
+ LdapName dn = new LdapName(groupDN);
+ for(Rdn rdn : dn.getRdns()) {
+ if(rdn.getType().equalsIgnoreCase(target)) {
+ groupList.add(rdn.getValue());
+ break;
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ _logger.log(Level.WARNING, "ldaprealm.searcherror", filter);
+ _logger.log(Level.WARNING, "security.exception", e);
+ }
+ return groupList;
+ }
+
+ /**
+ * Search for group membership using the given connection.
+ *
+ */
+ private List groupSearch(DirContext ctx, String baseDN,
+ String filter, String target)
+ {
+ List groupList = new ArrayList();
+
+ try {
+ String[] targets = new String[1];
+ targets[0] = target;
+
+ SearchControls ctls = new SearchControls();
+ ctls.setReturningAttributes(targets);
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+ NamingEnumeration e = ctx.search(baseDN,
+ filter.replaceAll(Matcher.quoteReplacement("\\"), Matcher.quoteReplacement("\\\\")), ctls);
+
+ while(e.hasMore()) {
+ SearchResult res = (SearchResult)e.next();
+ Attribute grpAttr = res.getAttributes().get(target);
+ int sz = grpAttr.size();
+ for (int i=0; i<sz; i++) {
+ String s = (String)grpAttr.get(i);
+ groupList.add(s);
+ }
+ }
+
+ } catch (Exception e) {
+ _logger.log(Level.WARNING, "ldaprealm.searcherror", filter);
+ _logger.log(Level.WARNING, "security.exception", e);
+ }
+
+ return groupList;
+ }
+
+ /**
+ * Do string substitution. target is replaced by value for all
+ * occurences.
+ *
+ */
+ private static void substitute(StringBuffer sb,
+ String target, String value)
+ {
+ int i = sb.indexOf(target);
+ while (i >= 0) {
+ sb.replace(i, i+target.length(), value);
+ i = sb.indexOf(target);
+ }
+ }
+ /**
+ * Escape special chars in search filter, according to RFC2254
+ * @param inName
+ * @return
+ */
+ private String RFC2254Encode(String inName) {
+
+ int len = inName.length();
+ StringBuffer buf = new StringBuffer(len);
+ for (int i = 0; i < len; i++) {
+ char ch = inName.charAt(i);
+ switch (ch) {
+ case '*' : buf.append("\\2a"); break;
+ case '(' : buf.append("\\28"); break;
+ case ')' : buf.append("\\29"); break;
+ case '\\' : buf.append("\\5c"); break;
+ case 0 : buf.append("\\00"); break;
+ default : buf.append(ch);
+ }
+ }
+ return buf.toString();
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/solaris/SolarisRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/solaris/SolarisRealm.java
new file mode 100644
index 0000000..5c7c2a5
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/auth/realm/solaris/SolarisRealm.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.auth.realm.solaris;
+
+import java.util.*;
+
+import java.util.logging.Level;
+
+import com.sun.enterprise.security.auth.realm.IASRealm;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.security.auth.realm.InvalidOperationException;
+import org.jvnet.hk2.annotations.Service;
+
+
+/**
+ * Realm wrapper for supporting Solaris authentication.
+ *
+ * <P>The Solaris realm needs the following properties in its configuration:
+ * <ul>
+ * <li>jaas-ctx - JAAS context name used to access LoginModule for
+ * authentication.
+ * </ul>
+ *
+ * @see com.sun.enterprise.security.auth.login.SolarisLoginModule
+ *
+ */
+@Service
+public final class SolarisRealm extends IASRealm
+{
+ // Descriptive string of the authentication type of this realm.
+ public static final String AUTH_TYPE = "solaris";
+ public static final String OS_ARCH = "os.arch";
+ public static final String SOL_SPARC_OS_ARCH = "sparc";
+ public static final String SOL_X86_OS_ARCH = "x86";
+
+ private HashMap groupCache;
+ private Vector emptyVector;
+ private static String osArchType = null;
+
+
+ // Library for native methods
+ static {
+ osArchType = System.getProperty(OS_ARCH);
+ if(SOL_SPARC_OS_ARCH.equals(osArchType)) {
+ System.loadLibrary("solsparcauth");
+ }
+ else if (SOL_X86_OS_ARCH.equals(osArchType)) {
+ System.loadLibrary("solx86auth");
+ }
+ }
+
+
+ /**
+ * Initialize a realm with some properties. This can be used
+ * when instantiating realms from their descriptions. This
+ * method may only be called a single time.
+ *
+ * @param props Initialization parameters used by this realm.
+ * @exception BadRealmException If the configuration parameters
+ * identify a corrupt realm.
+ * @exception NoSuchRealmException If the configuration parameters
+ * specify a realm which doesn't exist.
+ *
+ */
+ public synchronized void init(Properties props)
+ throws BadRealmException, NoSuchRealmException
+ {
+ super.init(props);
+ String jaasCtx = props.getProperty(IASRealm.JAAS_CONTEXT_PARAM);
+ if (jaasCtx == null) {
+ if (_logger.isLoggable(Level.WARNING)) {
+ _logger.warning("realmconfig.noctx");
+ }
+ String msg = sm.getString("solarisrealm.nojaas");
+ throw new BadRealmException(msg);
+ }
+
+ this.setProperty(IASRealm.JAAS_CONTEXT_PARAM, jaasCtx);
+
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.fine("SolarisRealm : "+IASRealm.JAAS_CONTEXT_PARAM+
+ "="+jaasCtx);
+ }
+
+ groupCache = new HashMap();
+ emptyVector = new Vector();
+ }
+
+
+ /**
+ * Returns a short (preferably less than fifteen characters) description
+ * of the kind of authentication which is supported by this realm.
+ *
+ * @return Description of the kind of authentication that is directly
+ * supported by this realm.
+ */
+ public String getAuthType()
+ {
+ return AUTH_TYPE;
+ }
+
+
+ /**
+ * Returns the name of all the groups that this user belongs to.
+ * This is called from web path role verification, though
+ * it should not be.
+ *
+ * @param username Name of the user in this realm whose group listing
+ * is needed.
+ * @return Enumeration of group names (strings).
+ * @exception InvalidOperationException thrown if the realm does not
+ * support this operation - e.g. Certificate realm does not support
+ * this operation.
+ */
+ public Enumeration getGroupNames (String username)
+ throws InvalidOperationException, NoSuchUserException
+ {
+ Vector v = (Vector)groupCache.get(username);
+ if (v == null) {
+ v = loadGroupNames(username);
+ }
+
+ return v.elements();
+ }
+
+
+ /**
+ * Set group membership info for a user.
+ *
+ * <P>See bugs 4646133,4646270 on why this is here.
+ *
+ */
+ private void setGroupNames(String username, String[] groups)
+ {
+ Vector v = null;
+
+ if (groups == null) {
+ v = emptyVector;
+
+ } else {
+ v = new Vector(groups.length + 1);
+ for (int i=0; i<groups.length; i++) {
+ v.add(groups[i]);
+ }
+ }
+
+ synchronized (this) {
+ groupCache.put(username, v);
+ }
+ }
+
+
+ /**
+ * Invoke the native authentication call.
+ *
+ * @param username User to authenticate.
+ * @param password Given password.
+ * @returns true of false, indicating authentication status.
+ *
+ */
+ public String[] authenticate(String username, char[] password)
+ {
+ String[] grps = nativeAuthenticate(username, new String(password));
+ if(grps != null){
+ grps = addAssignGroups(grps);
+ }
+ setGroupNames(username, grps);
+ return grps;
+ }
+
+
+ /**
+ * Loads groups names for the given user by calling native method.
+ *
+ * <P>Group info is loaded when user authenticates, however in some
+ * cases (such as run-as) the group membership info is needed
+ * without an authentication event.
+ *
+ */
+ private Vector loadGroupNames(String username)
+ {
+ String[] grps = nativeGetGroups(username);
+ if (grps == null) {
+ _logger.fine("No groups returned for user: "+username);
+ }
+
+ grps = addAssignGroups(grps);
+ setGroupNames(username, grps);
+ return (Vector)groupCache.get(username);
+ }
+
+
+ /**
+ * Native method. Authenticate using PAM.
+ *
+ */
+ private static native String[] nativeAuthenticate(String user,
+ String password);
+
+ /**
+ * Native method. Retrieve Solaris groups for user.
+ *
+ */
+ private static native String[] nativeGetGroups(String user);
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/authorize/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/authorize/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/authorize/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CLIUtil.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CLIUtil.java
new file mode 100644
index 0000000..c608fb9
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CLIUtil.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+import com.sun.enterprise.config.serverbeans.MessageSecurityConfig;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import java.util.List;
+import org.glassfish.api.ActionReport;
+
+/**
+ *
+ *
+ */
+public class CLIUtil {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CLIUtil.class);
+
+ /**
+ * Selects a config of interest from the domain, based on the target.
+ * (Eliminates duplicated code formerly in Create, Delete, and ListAuthRealm).
+ *
+ * @param domain
+ * @param target
+ * @return
+ */
+ static Config chooseConfig(final Domain domain,
+ final String target) {
+ Config config = null;
+ Config tmp = null;
+ try {
+ tmp = domain.getConfigs().getConfigByName(target);
+ } catch (Exception ex) {
+ }
+
+ if (tmp != null) {
+ return tmp;
+ }
+ Server targetServer = domain.getServerNamed(target);
+ if (targetServer != null) {
+ config = domain.getConfigNamed(targetServer.getConfigRef());
+ }
+ com.sun.enterprise.config.serverbeans.Cluster cluster = domain.getClusterNamed(target);
+ if (cluster != null) {
+ config = domain.getConfigNamed(cluster.getConfigRef());
+ }
+ return config;
+ }
+
+ static Config chooseConfig(final Domain domain,
+ final String target,
+ final ActionReport report) {
+ final Config config = chooseConfig(domain, target);
+ if (config == null) {
+ report.setMessage(localStrings.getLocalString(
+ "util.noconfigfortarget",
+ "Configuration for target {0} not found.", target));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ }
+ return config;
+ }
+
+ static boolean isRealmNew(final SecurityService securityService,
+ final String authRealmName) {
+
+ // check if there exists an auth realm byt he specified name
+ // if so return failure.
+ List<AuthRealm> authrealms = securityService.getAuthRealm();
+ for (AuthRealm authrealm : authrealms) {
+ if (authrealm.getName().equals(authRealmName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static AuthRealm findRealm(final SecurityService securityService,
+ String authRealmName) {
+ // ensure we have the file authrealm
+
+ if (authRealmName == null) {
+ authRealmName = securityService.getDefaultRealm();
+ }
+
+ for (AuthRealm authRealm : securityService.getAuthRealm()) {
+ if (authRealm.getName().equals(authRealmName)) {
+ return authRealm;
+ }
+ }
+ return null;
+ }
+
+ static JaccProvider findJaccProvider(final SecurityService securityService,
+ final String jaccProviderName) {
+ final List<JaccProvider> jaccProviders = securityService.getJaccProvider();
+ for (JaccProvider jaccProv : jaccProviders) {
+ if (jaccProv.getName().equals(jaccProviderName)) {
+ return jaccProv;
+ }
+ }
+ return null;
+ }
+
+ static MessageSecurityConfig findMessageSecurityConfig(final SecurityService securityService,
+ final String authLayer) {
+ List<MessageSecurityConfig> mscs = securityService.getMessageSecurityConfig();
+
+ for (MessageSecurityConfig msc : mscs) {
+ if (msc.getAuthLayer().equals(authLayer)) {
+ return msc;
+ }
+ }
+ return null;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ChangeAdminPassword.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ChangeAdminPassword.java
new file mode 100644
index 0000000..670cac3
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ChangeAdminPassword.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AdminService;
+import java.lang.annotation.Annotation;
+import java.util.Enumeration;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.util.List;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.glassfish.internal.api.Target;
+
+/**
+ * Change Admin Password Command
+ *
+ * Usage: change-admin-password [--user admin_user] [--terse=false]
+ * [--echo=false] [--host localhost] [--port 4848|4849]
+ * [--secure | -s]
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="change-admin-password")
+@PerLookup
+@I18n("change.admin.password")
+@ExecuteOn({RuntimeType.ALL})
+public class ChangeAdminPassword implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ChangeAdminPassword.class);
+
+ @Param(name="password", password=true)
+ private String oldpassword;
+
+ @Param(name="newpassword", password=true)
+ private String newpassword;
+
+ @Param(name="username", primary=true)
+ private String userName;
+
+ @Inject
+ private Configs configs;
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @Inject
+ private AdminService adminService;
+
+ private SecureAdmin secureAdmin = null;
+
+ private Config config;
+
+ @AccessRequired.To("update")
+ private AuthRealm fileAuthRealm;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ //Issue 17513 Fix - Check for null passwords if secureadmin is enabled
+ secureAdmin = domain.getSecureAdmin();
+ if (SecureAdmin.Util.isEnabled(secureAdmin)) {
+ if ((newpassword == null) || (newpassword.isEmpty())) {
+ report.setMessage(localStrings.getLocalString(
+ "null_empty_password","The new password is null or empty"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ }
+ final List <Config> configList = configs.getConfig();
+ config = configList.get(0);
+
+ SecurityService securityService = config.getSecurityService();
+
+ fileAuthRealm = null;
+ for (AuthRealm authRealm : securityService.getAuthRealm()) {
+ if (authRealm.getName().equals(adminService.getAuthRealmName())) {
+ fileAuthRealm = authRealm;
+ break;
+ }
+ }
+
+ if (fileAuthRealm == null) {
+ report.setMessage(localStrings.getLocalString(
+ "change.admin.password.adminrealmnotfound", "Server " +
+ "Error: There is no admin realm to perform this operation"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "change.admin.password.adminrealmnotsupported",
+ "Configured admin realm is not supported."));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "change.admin.password.keyfilenotfound",
+ "There is no physical file associated with admin realm"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // We have the right impl so let's get to updating existing user
+ FileRealm fr = null;
+ try {
+ realmsManager.createRealms(config);
+ fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(), fileAuthRealm.getName());
+ if (fr == null) {
+ throw new NoSuchRealmException(fileAuthRealm.getName());
+ }
+ } catch(NoSuchRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "change.admin.password.realmnotsupported",
+ "Configured admin realm does not exist.") +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+
+ //now updating admin user password
+ try {
+ Enumeration en = fr.getGroupNames(userName);
+ int size = 0;
+ while (en.hasMoreElements()) {
+ size++;
+ en.nextElement();
+ }
+ String[] groups = new String[size];
+ en = fr.getGroupNames(userName);
+ for (int i = 0; i < size; i++) {
+ groups[i] = (String) en.nextElement();
+ }
+ fr.updateUser(userName,userName, newpassword.toCharArray(), groups);
+ fr.persist();
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (Exception e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "change.admin.password.userupdatefailed",
+ "Password change failed for user named {0}", userName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuditModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuditModule.java
new file mode 100644
index 0000000..0dd1d96
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuditModule.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import org.jvnet.hk2.config.types.Property;
+import java.util.List;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.AuditModule;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.SecurityConfigListener;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+
+import java.beans.PropertyVetoException;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * Create Audit Module Command
+ *
+ * Usage: create-audit-module --classname classnme [--terse=false]
+ * [--echo=false] [--interactive=true] [--host localhost]
+ * [--port 4848|4849] [--secure | -s] [--user admin_user]
+ * [--passwordfile file_name] [--property (name=value)
+ * [:name=value]*] [--target target(Default server)] audit_module_name
+ *
+ * domain.xml element example
+ * <audit-module classname="com.foo.security.Audit" name="AM">
+ * <property name="auditOn" value="false"/>
+ * </audit-module>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="create-audit-module")
+@PerLookup
+@I18n("create.audit.module")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,CommandTarget.CONFIG})
+public class CreateAuditModule implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreateAuditModule.class);
+
+ @Param(name="classname")
+ String className;
+
+ @Param(name="auditmodulename", primary=true)
+ String auditModuleName;
+
+ @Param(optional=true, name="property", separator=':')
+ java.util.Properties properties;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ SecurityConfigListener securityConfigListener;
+
+ @AccessRequired.NewChild(type=AuditModule.class)
+ private SecurityService securityService = null;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ securityService = chooseSecurityService(context.getActionReport());
+ return (securityService != null);
+ }
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+
+ // check if there exists an audit module by the specified name
+ // if so return failure.
+ List<AuditModule> ams = securityService.getAuditModule();
+ for (AuditModule am : ams) {
+ if (am.getName().equals(auditModuleName)) {
+ report.setMessage(localStrings.getLocalString(
+ "create.audit.module.duplicatefound",
+ "AuditModule named {0} exists. " +
+ "Cannot add duplicate AuditModule.", auditModuleName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ }
+
+ // No duplicate audit modules found. So add one.
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ AuditModule newAuditModule = param.createChild(AuditModule.class);
+ populateAuditModuleElement(newAuditModule);
+ param.getAuditModule().add(newAuditModule);
+ return newAuditModule;
+ }
+ }, securityService);
+
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString("create.audit.module.fail",
+ "Creation of AuditModule {0} failed", auditModuleName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ //report.setMessage(localStrings.getLocalString("create.audit.module.success",
+ // "Creation of AuditModule {0} completed successfully", auditModuleName));
+ }
+
+ private SecurityService chooseSecurityService(final ActionReport report) {
+ config = CLIUtil.chooseConfig(domain, target, report);
+ if (config == null) {
+ return null;
+ }
+ return config.getSecurityService();
+ }
+
+ private void populateAuditModuleElement(AuditModule newAuditModule)
+ throws PropertyVetoException, TransactionFailure {
+ newAuditModule.setName(auditModuleName);
+ newAuditModule.setClassname(className);
+ if (properties != null) {
+ for (Object propname: properties.keySet()) {
+ Property newprop = newAuditModule.createChild(Property.class);
+ newprop.setName((String) propname);
+ newprop.setValue(properties.getProperty((String) propname));
+ newAuditModule.getProperty().add(newprop);
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuthRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuthRealm.java
new file mode 100644
index 0000000..367577c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateAuthRealm.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import java.util.List;
+import java.util.Properties;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.SecurityConfigListener;
+import com.sun.enterprise.security.common.Util;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.PropertyResolver;
+import org.glassfish.config.support.TargetType;
+import org.glassfish.internal.api.RelativePathResolver;
+
+
+/**
+ * CLI command to create JACC Provider
+ *
+ * Usage: create-auth-realm --classname realm_class [--terse=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--property (name=value)[:name=value]*]
+ * [--echo=false] [--target target(Default server)] auth_realm_name
+ *
+ * domain.xml element example
+ * <auth-realm name="file"
+ * classname="com.sun.enterprise.security.auth.realm.file.FileRealm">
+ * <property name="file" value="${com.sun.aas.instanceRoot}/config/keyfile"/>
+ * <property name="jaas-context" value="fileRealm"/>
+ * </auth-realm>
+ * Or
+ * <auth-realm name="certificate"
+ * classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm">
+ * </auth-realm>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="create-auth-realm")
+@PerLookup
+@I18n("create.auth.realm")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+public class CreateAuthRealm implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreateAuthRealm.class);
+
+ @Param(name="classname")
+ private String className;
+
+ @Param(name="authrealmname", primary=true)
+ private String authRealmName;
+
+ @Param(optional=true, name="property", separator=':')
+ private Properties properties;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Configs configs;
+
+ @Inject
+ private Domain domain;
+ @Inject
+ private SecurityConfigListener securityListener;
+
+ //initialize the habitat in Util needed by Realm classes
+ @Inject
+ private Util util;
+
+ @AccessRequired.NewChild(type=AuthRealm.class)
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ if ( ! ensureRealmIsNew(context.getActionReport())) {
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ // No duplicate auth realms found. So add one.
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ AuthRealm newAuthRealm = param.createChild(AuthRealm.class);
+ populateAuthRealmElement(newAuthRealm);
+ param.getAuthRealm().add(newAuthRealm);
+ //In case of cluster instances, this is required to
+ //avoid issues with the listener's callback method
+ SecurityConfigListener.authRealmCreated(config, newAuthRealm);
+ return newAuthRealm;
+
+ }
+ }, securityService);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString("create.auth.realm.fail",
+ "Creation of Authrealm {0} failed", authRealmName) +
+ " " + e.getLocalizedMessage() );
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ }
+
+ private void populateAuthRealmElement(AuthRealm newAuthRealm)
+ throws PropertyVetoException, TransactionFailure {
+ newAuthRealm.setName(authRealmName);
+ newAuthRealm.setClassname(className);
+ if (properties != null) {
+ for (Object propname: properties.keySet()) {
+ Property newprop = newAuthRealm.createChild(Property.class);
+ newprop.setName((String) propname);
+ String propValue = properties.getProperty((String) propname);
+ newprop.setValue(propValue);
+ newAuthRealm.getProperty().add(newprop);
+ }
+ }
+ }
+
+ private boolean ensureRealmIsNew(final ActionReport report){
+ if ( ! CLIUtil.isRealmNew(securityService, authRealmName)) {
+ report.setMessage(localStrings.getLocalString(
+ "create.auth.realm.duplicatefound",
+ "Authrealm named {0} exists. Cannot add duplicate AuthRealm.",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateFileUser.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateFileUser.java
new file mode 100644
index 0000000..6fcb5bd
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateFileUser.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AdminService;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import java.io.File;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Create File User Command
+ * Usage: create-file-user [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s]
+ * [--user admin_user] [--userpassword admin_passwd]
+ * [--passwordfile file_name] [--groups user_groups[:user_groups]*]
+ * [--authrealmname authrealm_name] [--target target(Default server)]
+ * username
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="create-file-user")
+@PerLookup
+@I18n("create.file.user")
+@ExecuteOn({RuntimeType.ALL})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=AuthRealm.class,
+ opType=RestEndpoint.OpType.POST,
+ path="create-user",
+ description="Create",
+ params={
+ @RestParam(name="authrealmname", value="$parent")
+ })
+})
+public class CreateFileUser implements /*UndoableCommand*/ AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreateFileUser.class);
+
+ @Param(name="groups", optional=true, separator=':')
+ private List<String> groups = new ArrayList<String>(0); //by default, an empty list is better than a null
+
+ //TODO: this is still a String, need to convert to char[]
+ @Param(name="userpassword", password=true)
+ private String userpassword;
+
+ @Param(name="authrealmname", optional=true)
+ private String authRealmName;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Param(name="username", primary=true)
+ private String userName;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @Inject
+ private ServerEnvironment se;
+
+ @Inject
+ private AdminService adminService;
+
+ private SecureAdmin secureAdmin = null;
+
+ @AccessRequired.To("update")
+ private AuthRealm fileAuthRealm;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ fileAuthRealm = CLIUtil.findRealm(securityService, authRealmName);
+ if (fileAuthRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "create.file.user.filerealmnotfound",
+ "File realm {0} does not exist",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ /*
+ * The realm might have been defaulted, so capture the actual name.
+ */
+ authRealmName = fileAuthRealm.getName();
+ return true;
+ }
+
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+
+
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "create.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.",
+ fileRealmClassName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ final String kf = keyFile;
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString("create.file.user.keyfilenotfound",
+ "There is no physical file associated with this file realm {0} ",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ boolean exists = (new File(kf)).exists();
+ if (!exists) {
+ report.setMessage(
+ localStrings.getLocalString("file.realm.keyfilenonexistent",
+ "The specified physical file {0} associated with the file realm {1} does not exist.",
+ new Object[]{kf, authRealmName}));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ // Now get all inputs ready. userid and groups are straightforward but
+ // password is tricky. It is stored in the file passwordfile passed
+ // through the CLI options. It is stored under the name
+ // AS_ADMIN_USERPASSWORD. Fetch it from there.
+ final String password = userpassword; // fetchPassword(report);
+ if (password == null) {
+ report.setMessage(localStrings.getLocalString(
+ "create.file.user.keyfilenotreadable", "Password for user {0} " +
+ "has to be specified in --userpassword option or supplied " +
+ "through AS_ADMIN_USERPASSWORD property in the file specified " +
+ "in --passwordfile option", userName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ //Issue 17525 Fix - Check for null passwords for admin-realm if secureadmin is enabled
+ secureAdmin = domain.getSecureAdmin();
+ if ((SecureAdmin.Util.isEnabled(secureAdmin))
+ && (authRealmName.equals(adminService.getAuthRealmName()))) {
+ if (password.isEmpty()) {
+ report.setMessage(localStrings.getLocalString(
+ "null_empty_password","The admin user password is null or empty"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ }
+ // now adding user
+ try {
+ //even though create-file-user is not an update to the security-service
+ //do we need to make it transactional by referncing the securityservice
+ //hypothetically ?.
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ try {
+ realmsManager.createRealms(config);
+ //If the (shared) keyfile is updated by an external process, load the users first
+ refreshRealm(config.getName(),authRealmName);
+ final FileRealm fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(),authRealmName);
+ CreateFileUser.handleAdminGroup(authRealmName, groups);
+ String[] groups1 = groups.toArray(new String[groups.size()]);
+ try {
+ fr.addUser(userName, password.toCharArray(), groups1);
+ }catch(BadRealmException br) {
+ //Check if the server environment is DAS. If is not DAS (user creation was
+ //successful on DAS), then the error is caused in the instances because of shared keyfile between
+ // DAS and cluster instances - ignore the exception for instances.
+
+ if(se != null && se.isDas()) {
+ throw new BadRealmException(br);
+ }
+ }
+ fr.persist();
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (Exception e) {
+ String localalizedErrorMsg = (e.getLocalizedMessage() == null)?"":e.getLocalizedMessage();
+ report.setMessage(
+ localStrings.getLocalString("create.file.user.useraddfailed",
+ "Adding User {0} to the file realm {1} failed",
+ userName, authRealmName) + " " + localalizedErrorMsg);
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ return null;
+ }
+ }, securityService);
+
+ } catch (Exception e) {
+ report.setMessage(
+ localStrings.getLocalString("create.file.user.useraddfailed",
+ "Adding User {0} to the file realm {1} failed",
+ userName, authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+
+ /* private String fetchPassword(ActionReport report) {
+ String password = null;
+ if (userpassword != null && passwordFile != null)
+ return password;
+ if (userpassword != null)
+ password = userpassword;
+ if (passwordFile != null) {
+ File passwdFile = new File(passwordFile);
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(passwdFile));
+ Properties prop = new Properties();
+ prop.load(is);
+ for (Enumeration e=prop.propertyNames(); e.hasMoreElements();) {
+ String entry = (String)e.nextElement();
+ if (entry.equals("AS_ADMIN_USERPASSWORD")) {
+ password = prop.getProperty(entry);
+ break;
+ }
+ }
+ } catch(Exception e) {
+ report.setFailureCause(e);
+ } finally {
+ try {
+ if (is != null)
+ is.close();
+ } catch(final Exception ignore){}
+ }
+ }
+ return password;
+ } */
+
+ public static void refreshRealm(String configName, String realmName) {
+ if (realmName != null && realmName.length() > 0) {
+ try {
+ Realm realm = Realm.getInstance(configName, realmName);
+
+ if (realm != null) {
+ realm.refresh(configName);
+ }
+ } catch (com.sun.enterprise.security.auth.realm.NoSuchRealmException nre) {
+ // _logger.fine("Realm: "+realmName+" is not configured");
+ } catch (com.sun.enterprise.security.auth.realm.BadRealmException bre) {
+ // _logger.fine("Realm: "+realmName+" is not configured");
+ }
+ }
+ }
+ static void handleAdminGroup(String lr, List<String> lg) {
+ String fr = "admin-realm"; //this should be a constant defined at a central place -- the name of realm for admin
+ String fg = "asadmin"; //this should be a constant defined at a central place -- fixed name of admin group
+ if (fr.equals(lr) && lg != null) {
+ lg.clear(); //basically, we are ignoring the group specified on command line when it's admin realm
+ lg.add(fg);
+ }
+ }
+
+// @Override
+// public ActionReport prepare(ParameterMap parameters) {
+// //TODO: is there a way to check if in a Cluster some
+// //instances are down
+//// com.sun.enterprise.config.serverbeans.Cluster cluster = domain.getClusterNamed(target);
+//// if (cluster!=null) {
+//// List<Server> servers = cluster.getInstances();
+//// }
+// final ActionReport report = new ActionReport();
+// }
+//
+// @Override
+// public void undo(ParameterMap parameters) {
+// throw new UnsupportedOperationException("Not supported yet.");
+// }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateJACCProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateJACCProvider.java
new file mode 100644
index 0000000..c90d6f3
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateJACCProvider.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import java.util.Properties;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ * Create Jacc Provider Command
+ *
+ * Usage: create-jacc-provider --policyconfigfactoryclass pc_factory_class
+ * --policyproviderclass pol_provider_class
+ * [--help] [--user admin_user] [--passwordfile file_name]
+ * [ --property (name=value)[:name=value]*]
+ * [ --target target_name] jacc_provider_name
+ *
+ *
+ * domain.xml element example
+ * <jacc-provider policy-provider="com.sun.enterprise.security.provider.PolicyWrapper" name="default" policy-configuration-factory-provider="com.sun.enterprise.security.provider.PolicyConfigurationFactoryImpl">
+ * <property name="repository" value="${com.sun.aas.instanceRoot}/generated/policy" />
+ * </jacc-provider>
+ *
+ */
+@Service(name="create-jacc-provider")
+@PerLookup
+@I18n("create.jacc.provider")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+public class CreateJACCProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreateJACCProvider.class);
+
+ @Param(name="policyconfigfactoryclass", alias="policyConfigurationFactoryProvider")
+ private String polConfFactoryClass;
+
+ @Param(name="policyproviderclass", alias="policyProvider")
+ private String polProviderClass;
+
+ @Param(name="jaccprovidername", primary=true)
+ private String jaccProviderName;
+
+ @Param(optional=true, name="property", separator=':')
+ private Properties properties;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.NewChild(type=JaccProvider.class)
+ private SecurityService securityService;
+
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ JaccProvider jaccProvider = CLIUtil.findJaccProvider(securityService, jaccProviderName);
+ if (jaccProvider != null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "create.jacc.provider.duplicatefound",
+ "JaccProvider named {0} exists. Cannot add duplicate JaccProvider.",
+ jaccProviderName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ // No duplicate auth realms found. So add one.
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ JaccProvider newJacc = param.createChild(JaccProvider.class);
+ newJacc.setName(jaccProviderName);
+ newJacc.setPolicyConfigurationFactoryProvider(polConfFactoryClass);
+ newJacc.setPolicyProvider(polProviderClass);
+ param.getJaccProvider().add(newJacc);
+ return newJacc;
+ }
+ }, securityService);
+
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString("create.auth.realm.fail",
+ "Creation of Authrealm {0} failed", jaccProviderName) +
+ " " + e.getLocalizedMessage() );
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateMessageSecurityProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateMessageSecurityProvider.java
new file mode 100644
index 0000000..9b5cb91
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreateMessageSecurityProvider.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.RequestPolicy;
+import java.util.List;
+import java.util.Properties;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.MessageSecurityConfig;
+import com.sun.enterprise.config.serverbeans.ProviderConfig;
+import com.sun.enterprise.config.serverbeans.ResponsePolicy;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+
+import java.beans.PropertyVetoException;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.jvnet.hk2.config.ConfigListener;
+
+/**
+ * Create Message Security Provider Command
+ *
+ * Usage: create-message-security-provider [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--target target(Default server)] [--layer message_layer=SOAP]
+ * [--providertype provider_type] [--requestauthsource request_auth_source]
+ * [--requestauthrecipient request_auth_recipient]
+ * [--responseauthsource response_auth_source]
+ * [--responseauthrecipient response_auth_recipient] [--isdefaultprovider]
+ * [--property (name=value)[:name=value]*] --classname provider_class
+ * provider_name
+ *
+ * domain.xml element example
+ *
+ * <message-security-config auth-layer="SOAP">
+ * <!-- turned off by default -->
+ * <provider-config class-name="com.sun.wss.provider.ClientSecAuthModule"
+ * provider-id="XWS_ClientProvider" provider-type="client">
+ * <request-policy auth-source="content"/>
+ * <response-policy auth-source="content"/>
+ * <property name="encryption.key.alias" value="s1as"/>
+ * <property name="signature.key.alias" value="s1as"/>
+ * <property name="dynamic.username.password" value="false"/>
+ * <property name="debug" value="false"/>
+ * </provider-config>
+ * </message-security-config>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="create-message-security-provider")
+@PerLookup
+@I18n("create.message.security.provider")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,CommandTarget.CONFIG})
+public class CreateMessageSecurityProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreateMessageSecurityProvider.class);
+
+ private static final String SERVER = "server";
+ private static final String CLIENT = "client";
+ private static final String CLIENT_SERVER = "client-server";
+
+ // auth-layer can only be SOAP | HttpServlet
+ @Param(name="layer", acceptableValues="SOAP,HttpServlet",
+ defaultValue="SOAP")
+ String authLayer;
+
+ // provider-type can only be - client | server | 'client-server'
+ @Param(name="providertype", acceptableValues="client,server,client-server",
+ optional=true, defaultValue="client-server")
+ String providerType;
+
+ // auth-source can only be - sender | content
+ @Param(name="requestauthsource", optional=true)
+ String requestAuthSource;
+
+ // auth-recipient can only be - before-content | after-content
+ @Param(name="requestauthrecipient", optional=true)
+ String requestAuthRecipient;
+
+ // auth-source can only be - sender | content
+ @Param(name="responseauthsource", optional=true)
+ String responseAuthSource;
+
+ // auth-recipient can only be - before-content | after-content
+ @Param(name="responseauthrecipient", optional=true)
+ String responseAuthRecipient;
+
+ // isdefaultprovider can only be - client | server | 'client-server'
+ @Param(name="isdefaultprovider", optional=true, defaultValue="false")
+ Boolean isDefaultProvider;
+
+ @Param(optional=true, name="property", separator=':')
+ Properties properties;
+
+ @Param(name="classname")
+ String providerClass;
+
+ @Param(name="providername", primary=true)
+ String providerId;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.NewChild(type=MessageSecurityConfig.class)
+ private SecurityService secService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ secService = config.getSecurityService();
+ return true;
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are parameter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ List<MessageSecurityConfig> mscs = secService.getMessageSecurityConfig();
+
+ // Let's find the correct MessageSecurityConfig. As of now,
+ // there can be only two of them - one for SOAP and one for
+ // HttpServlet
+ MessageSecurityConfig msgSecCfg = null;
+ for (MessageSecurityConfig msc : mscs) {
+ if (msc.getAuthLayer().equals(authLayer)) {
+ msgSecCfg = msc;
+ }
+ }
+
+ // If there is message security config for this type of layer
+ // then, add a new provider config under it provided it is not duplicate
+ if (msgSecCfg != null) {
+ // check if there exists a provider config by the
+ // specified provider name; if so return failure.
+ List<ProviderConfig> pcs = msgSecCfg.getProviderConfig();
+ for (ProviderConfig pc : pcs) {
+ if (pc.getProviderId().equals(providerId)) {
+ report.setMessage(localStrings.getLocalString(
+ "create.message.security.provider.duplicatefound",
+ "Message security provider named {0} exists. " +
+ "Cannot add duplicate.", providerId));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ }
+
+ // No duplicate message security providers found. So add one.
+ try {
+ ConfigSupport.apply(new SingleConfigCode<MessageSecurityConfig>() {
+ public Object run(MessageSecurityConfig param)
+ throws PropertyVetoException, TransactionFailure {
+ ProviderConfig newPC = param.createChild(ProviderConfig.class);
+ populateProviderConfigElement(newPC);
+ param.getProviderConfig().add(newPC);
+ // Depending on the providerType of the new provider
+ // the isDefaultProvider=true results in creation of
+ // either default-provider attribute or
+ // default-client-provider or BOTH in the message
+ // security config object
+ if (isDefaultProvider) {
+ if (providerType.equals(SERVER) ||
+ providerType.equals(CLIENT_SERVER) )
+ param.setDefaultProvider(providerId);
+
+ if (providerType.equals(CLIENT) ||
+ providerType.equals(CLIENT_SERVER) )
+ param.setDefaultClientProvider(providerId);
+ }
+ return newPC;
+ }
+ }, msgSecCfg);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString(
+ "create.message.security.provider.fail",
+ "Creation of message security provider named {0} failed",
+ providerId));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ report.setMessage(localStrings.getLocalString(
+ "create.message.security.provider.success",
+ "Creation of message security provider named {0} completed " +
+ "successfully", providerId));
+ }
+ // Now if there is NO message security config for this type of layer
+ // then, first add a message security config for the layer and then
+ // add a provider config under this message security config
+ else {
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ MessageSecurityConfig newMSC = param.createChild(MessageSecurityConfig.class);
+ newMSC.setAuthLayer(authLayer);
+ param.getMessageSecurityConfig().add(newMSC);
+
+ ProviderConfig newPC = newMSC.createChild(ProviderConfig.class);
+
+ populateProviderConfigElement(newPC);
+ newMSC.getProviderConfig().add(newPC);
+ // Depending on the providerType of the new provider
+ // the isDefaultProvider=true results in creation of
+ // either default-provider attribute or
+ // default-client-provider or BOTH in the message
+ // security config object
+ if (isDefaultProvider) {
+ if (providerType.equals(SERVER) ||
+ providerType.equals(CLIENT_SERVER) )
+ newMSC.setDefaultProvider(providerId);
+
+ if (providerType.equals(CLIENT) ||
+ providerType.equals(CLIENT_SERVER) )
+ newMSC.setDefaultClientProvider(providerId);
+ }
+ return newMSC;
+ }
+ }, secService);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString(
+ "create.message.security.provider.fail",
+ "Creation of message security provider named {0} failed",
+ providerId));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ /* report.setMessage(localStrings.getLocalString(
+ "create.message.security.provider.success",
+ "Creation of message security provider named {0} completed " +
+ "successfully", providerId)); */
+ }
+ }
+
+ private void populateProviderConfigElement(ProviderConfig newProviderConfig)
+ throws PropertyVetoException, TransactionFailure {
+
+ newProviderConfig.setClassName(providerClass);
+ newProviderConfig.setProviderId(providerId);
+ newProviderConfig.setProviderType(providerType);
+
+ // create a new RequestPolicy config and add as child of this
+ // new Provider Config
+ RequestPolicy reqPolicy = newProviderConfig.createChild(RequestPolicy.class);
+ reqPolicy.setAuthSource(requestAuthSource);
+ reqPolicy.setAuthRecipient(requestAuthRecipient);
+ newProviderConfig.setRequestPolicy(reqPolicy);
+
+ // create a new ResponsePolicy config and add as child of this
+ // new Provider Config
+ ResponsePolicy respPolicy = newProviderConfig.createChild(ResponsePolicy.class);
+ respPolicy.setAuthSource(responseAuthSource);
+ respPolicy.setAuthRecipient(responseAuthRecipient);
+ newProviderConfig.setResponsePolicy(respPolicy);
+
+ // add properties
+ if (properties != null) {
+ for (Object propname: properties.keySet()) {
+ Property newprop = newProviderConfig.createChild(Property.class);
+ newprop.setName((String) propname);
+ newprop.setValue(properties.getProperty((String) propname));
+ newProviderConfig.getProperty().add(newprop);
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreatePasswordAlias.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreatePasswordAlias.java
new file mode 100644
index 0000000..77ea5db
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/CreatePasswordAlias.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+
+/**
+ * Create Password Alias Command
+ *
+ * Usage: create-password-alias [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name] aliasname
+ *
+ * Result of the command is that:
+ * <domain-dir>/<domain-name>/config/domain-passwords file gets appended with
+ * the entry of the form: aliasname=<password encrypted with masterpassword>
+ *
+ * A user can use this aliased password now in setting passwords in domain.xml.
+ * Benefit is it is in NON-CLEAR-TEXT
+ *
+ * domain.xml example entry is:
+ * <provider-config class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule"
+ * provider-id="XWS_ClientProvider" provider-type="client">
+ * <property name="password" value="${ALIAS=myalias}/>
+ * </provider-config>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="create-password-alias")
+@PerLookup
+@I18n("create.password.alias")
+@ExecuteOn(RuntimeType.ALL)
+@TargetType({CommandTarget.DAS,CommandTarget.DOMAIN})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST,
+ path="create-password-alias",
+ description="create-password-alias")
+})
+@AccessRequired(resource="domain/passwordAliases", action="create")
+public class CreatePasswordAlias implements AdminCommand {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreatePasswordAlias.class);
+
+ @Param(name="aliasname", primary=true)
+ private String aliasName;
+
+ @Param(name="aliaspassword", password=true)
+ private String aliasPassword;
+
+ @Inject
+ private DomainScopedPasswordAliasStore domainPasswordAliasStore;
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are parameter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ try {
+ if (domainPasswordAliasStore.containsKey(aliasName)) {
+ report.setMessage(localStrings.getLocalString(
+ "create.password.alias.alreadyexists",
+ "Password alias with the specified name already exists. " +
+ "Please use the update-password-alias command to change it",
+ aliasName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ domainPasswordAliasStore.put(aliasName, aliasPassword.toCharArray());
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ report.setMessage(localStrings.getLocalString(
+ "create.password.alias.fail",
+ "Creation of Password Alias {0} failed", aliasName)+
+ " " + ex.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(ex);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ /*report.setMessage(localStrings.getLocalString(
+ "create.password.alias.success",
+ "Encrypted password for the alias name {0} stored successfully",
+ aliasName)); */
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuditModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuditModule.java
new file mode 100644
index 0000000..a9aa9f7
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuditModule.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AuditModule;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.SecurityConfigListener;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+
+import java.beans.PropertyVetoException;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * Delete Audit Module Command
+ *
+* Usage: delete-audit-module [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--target target(Default server)] auth_realm_name
+ *
+ * @author Nandini Ektare
+ */
+@Service(name="delete-audit-module")
+@PerLookup
+@I18n("delete.audit.module")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,CommandTarget.CONFIG})
+public class DeleteAuditModule implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteAuditModule.class);
+
+ @Param(name="auditmodulename", primary=true)
+ String auditModuleName;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.To(value="delete")
+ private AuditModule auditModule = null;
+
+ @Inject
+ SecurityConfigListener securityConfigListener;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ auditModule = chooseAuditModule(context.getActionReport());
+ return true;
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ ActionReport report = context.getActionReport();
+
+ try {
+ if (auditModule == null) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.audit.module.notfound",
+ "Specified Audit Module {0} not found", auditModuleName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+
+ param.getAuditModule().remove(auditModule);
+ return null;
+ }
+ }, securityService);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.audit.module.fail", "Deletion of Audit Module {0} failed",
+ auditModuleName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+
+ /*report.setMessage(localStrings.getLocalString("delete.audit.module.success",
+ "Deletion of Audit Module {0} completed successfully", auditModuleName));*/
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ }
+
+ private AuditModule chooseAuditModule(final ActionReport report) {
+ config = CLIUtil.chooseConfig(domain, target, report);
+ if (config == null) {
+ return null;
+ }
+ securityService = config.getSecurityService();
+ for (AuditModule am : securityService.getAuditModule()) {
+ if (am.getName().equals(auditModuleName)) {
+ return am;
+ }
+ }
+ return null;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuthRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuthRealm.java
new file mode 100644
index 0000000..d0a0279
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteAuthRealm.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.SecurityConfigListener;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * Delete Auth Realm Command
+ *
+* Usage: delete-auth-realm [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--target target(Default server)] auth_realm_name
+ *
+ * @author Nandini Ektare
+ */
+@Service(name="delete-auth-realm")
+@PerLookup
+@I18n("delete.auth.realm")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+public class DeleteAuthRealm implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteAuthRealm.class);
+
+ @Param(name="authrealmname", primary=true)
+ private String authRealmName;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+ // @Inject
+ // private SecurityConfigListener securityListener;
+
+ @AccessRequired.To("delete")
+ AuthRealm authRealm = null;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ authRealm = findRealm();
+ if (authRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "delete.auth.realm.notfound",
+ "Authrealm named {0} not found", authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ }
+ return (authRealm != null);
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ ActionReport report = context.getActionReport();
+
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ param.getAuthRealm().remove(authRealm);
+ //temporary fix - since the SecurityConfigListener is not being called on an realm delete.
+ SecurityConfigListener.authRealmDeleted(authRealm);
+ return null;
+ }
+ }, securityService);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.auth.realm.fail", "Deletion of Authrealm {0} failed",
+ authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ }
+
+ private AuthRealm findRealm() {
+ for (AuthRealm realm : securityService.getAuthRealm()) {
+ if (realm.getName().equals(authRealmName)) {
+ return realm;
+ }
+ }
+ return null;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteFileUser.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteFileUser.java
new file mode 100644
index 0000000..2bec084
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteFileUser.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import java.io.File;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+
+/**
+ * Delete File User Command
+ * Usage: delete-file-user [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s] [--user admin_user]
+ * [--passwordfile file_name] [--authrealmname authrealm_name]
+ * [--target target(Default server)] username
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="delete-file-user")
+@PerLookup
+@I18n("delete.file.user")
+@ExecuteOn({RuntimeType.ALL})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=AuthRealm.class,
+ opType=RestEndpoint.OpType.DELETE,
+ path="delete-user",
+ description="Delete",
+ params={
+ @RestParam(name="authrealmname", value="$parent")
+ })
+})
+public class DeleteFileUser implements /*UndoableCommand*/ AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteFileUser.class);
+
+ @Param(name="authrealmname", optional=true)
+ private String authRealmName;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Param(name="username", primary=true)
+ private String userName;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+ @Inject
+ private RealmsManager realmsManager;
+
+ @AccessRequired.To("update")
+ private AuthRealm fileAuthRealm;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ fileAuthRealm = CLIUtil.findRealm(securityService, authRealmName);
+ if (fileAuthRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "delete.file.user.filerealmnotfound",
+ "File realm {0} does not exist", authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ /*
+ * The realm might have been defaulted, so capture the actual name.
+ */
+ authRealmName = fileAuthRealm.getName();
+ return true;
+ }
+
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "delete.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.",
+ fileRealmClassName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ final String kFile = keyFile;
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString("delete.file.user.keyfilenotfound",
+ "There is no physical file associated with this file realm {0} ",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ boolean exists = (new File(kFile)).exists();
+ if (!exists) {
+ report.setMessage(
+ localStrings.getLocalString("file.realm.keyfilenonexistent",
+ "The specified physical file {0} associated with the file realm {1} does not exist.",
+ new Object[]{kFile, authRealmName}));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ //even though delete-file-user is not an update to the security-service
+ //do we need to make it transactional by referncing the securityservice
+ //hypothetically ?.
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ try {
+ realmsManager.createRealms(config);
+ final FileRealm fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(),authRealmName);
+ fr.removeUser(userName);
+ fr.persist();
+ CreateFileUser.refreshRealm(config.getName(),authRealmName);
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (NoSuchUserException e) {
+ report.setMessage(
+ localStrings.getLocalString("delete.file.user.usernotfound",
+ "There is no such existing user {0} in the file realm {1}.",
+ userName, authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ } catch (BadRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "delete.file.user.realmcorrupted",
+ "Configured file realm {0} is corrupted.", authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ report.setMessage(
+ localStrings.getLocalString("delete.file.user.userdeletefailed",
+ "Removing User {0} from file realm {1} failed",
+ userName, authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ return null;
+ }
+ }, securityService);
+ } catch (Exception e) {
+ report.setMessage(
+ localStrings.getLocalString("delete.file.user.userdeletefailed",
+ "Removing User {0} from file realm {1} failed",
+ userName, authRealmName) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+// @Override
+// public ActionReport prepare(ParameterMap parameters) {
+// //TODO: is there a way to check if in a Cluster some
+// //instances are down
+//// com.sun.enterprise.config.serverbeans.Cluster cluster = domain.getClusterNamed(target);
+//// if (cluster!=null) {
+//// List<Server> servers = cluster.getInstances();
+//// }
+// final ActionReport report = new ActionReport();
+// }
+//
+// @Override
+// public void undo(ParameterMap parameters) {
+// throw new UnsupportedOperationException("Not supported yet.");
+// }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteJaccProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteJaccProvider.java
new file mode 100644
index 0000000..54fc455
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteJaccProvider.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.beans.PropertyVetoException;
+import java.util.List;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+
+/**
+ *Usage: delete-jacc-provider
+ * [--help] [--user admin_user] [--passwordfile file_name]
+ * [ --target target_name] jacc_provider_name
+ *
+ */
+@Service(name="delete-jacc-provider")
+@PerLookup
+@I18n("delete.jacc.provider")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+public class DeleteJaccProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteJaccProvider.class);
+
+ @Param(name="jaccprovidername", primary=true)
+ private String jaccprovider;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ private SecurityService securityService;
+
+ @AccessRequired.To("delete")
+ private JaccProvider jprov;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ config = CLIUtil.chooseConfig(domain, target, report);
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ jprov = CLIUtil.findJaccProvider(securityService, jaccprovider);
+ if (jprov == null) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.jacc.provider.notfound",
+ "JaccProvider named {0} not found", jaccprovider));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ if ("default".equals(jprov.getName())
+ || "simple".equals(jprov.getName())) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.jacc.provider.notallowed",
+ "JaccProvider named {0} is a system provider and cannot be deleted", jaccprovider));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ try {
+ List<JaccProvider> jaccProviders = securityService.getJaccProvider();
+ JaccProvider jprov = null;
+ for (JaccProvider jaccProv : jaccProviders) {
+ if (jaccProv.getName().equals(jaccprovider)) {
+ jprov = jaccProv;
+ break;
+ }
+ }
+
+ final JaccProvider jaccprov = jprov;
+ ConfigSupport.apply(new SingleConfigCode<SecurityService>() {
+ public Object run(SecurityService param)
+ throws PropertyVetoException, TransactionFailure {
+ param.getJaccProvider().remove(jaccprov);
+ return null;
+ }
+ }, securityService);
+ } catch(TransactionFailure e) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.jacc.provider.fail", "Deletion of JaccProvider {0} failed",
+ jaccprovider) + " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteMessageSecurityProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteMessageSecurityProvider.java
new file mode 100644
index 0000000..ac20b97
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeleteMessageSecurityProvider.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.MessageSecurityConfig;
+import com.sun.enterprise.config.serverbeans.ProviderConfig;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+
+import java.beans.PropertyVetoException;
+import java.util.List;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.jvnet.hk2.config.ConfigListener;
+
+/**
+ * Delete Message Security Provider Command
+ *
+ * Usage: delete-message-security-provider --layer message_layer [--terse=false]
+ * [--echo=false] [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--target target(Defaultserver)] provider_name
+ *
+ * @author Nandini Ektare
+ */
+@Service(name="delete-message-security-provider")
+@PerLookup
+@I18n("delete.message.security.provider")
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,CommandTarget.CONFIG})
+public class DeleteMessageSecurityProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteMessageSecurityProvider.class);
+
+ @Param(name="providername", primary=true)
+ String providerId;
+
+ // auth-layer can only be SOAP | HttpServlet
+ @Param(name="layer",defaultValue="SOAP")
+ String authLayer;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ ProviderConfig thePC = null;
+
+ @AccessRequired.To("delete")
+ private MessageSecurityConfig msgSecCfg = null;
+
+ private SecurityService secService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ secService = config.getSecurityService();
+ msgSecCfg = CLIUtil.findMessageSecurityConfig(secService, authLayer);
+ if (msgSecCfg == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "delete.message.security.provider.confignotfound",
+ "A Message security config does not exist for the layer {0}",
+ authLayer));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ ActionReport report = context.getActionReport();
+
+ List<ProviderConfig> pcs = msgSecCfg.getProviderConfig();
+ for (ProviderConfig pc : pcs) {
+ if (pc.getProviderId().equals(providerId)) {
+ thePC = pc;
+ try {
+ ConfigSupport.apply(
+ new SingleConfigCode<MessageSecurityConfig>() {
+
+ public Object run(MessageSecurityConfig param)
+ throws PropertyVetoException, TransactionFailure {
+
+ if ((param.getDefaultProvider() != null) &&
+ param.getDefaultProvider().equals(
+ thePC.getProviderId())) {
+ param.setDefaultProvider(null);
+ }
+
+ if ((param.getDefaultClientProvider() != null) &&
+ param.getDefaultClientProvider().equals(
+ thePC.getProviderId())) {
+ param.setDefaultClientProvider(null);
+ }
+
+ param.getProviderConfig().remove(thePC);
+ return null;
+ }
+ }, msgSecCfg);
+ } catch(TransactionFailure e) {
+ e.printStackTrace();
+ report.setMessage(localStrings.getLocalString(
+ "delete.message.security.provider.fail",
+ "Deletion of message security provider named {0} failed",
+ providerId));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+ /*report.setMessage(localStrings.getLocalString(
+ "delete.message.security.provider.success",
+ "Deletion of message security provider {0} completed " +
+ "successfully", providerId));*/
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ return;
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeletePasswordAlias.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeletePasswordAlias.java
new file mode 100644
index 0000000..bdd02bd
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/DeletePasswordAlias.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+ * Delete Password Alias Command
+ *
+ * Usage: delete-password-alias [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name] aliasname
+ *
+ * Result of the command is that:
+ * The entry of the form: aliasname=<password-encrypted-with-masterpassword>
+ * in <domain-dir>/<domain-name>/config/domain-passwords file is removed
+ *
+ * domain.xml example entry is:
+ * <provider-config class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule"
+ * provider-id="XWS_ClientProvider" provider-type="client">
+ * <property name="password" value="${ALIAS=myalias}/>
+ * </provider-config>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="delete-password-alias")
+@PerLookup
+@I18n("delete.password.alias")
+@ExecuteOn(RuntimeType.ALL)
+@TargetType({CommandTarget.DAS,CommandTarget.DOMAIN})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST, // TODO: Should be DELETE
+ path="delete-password-alias",
+ description="delete-password-alias")
+})
+
+@AccessRequired(resource="domain/passwordAliases/passwordAlias/$aliasName", action="delete")
+public class DeletePasswordAlias implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeletePasswordAlias.class);
+
+ @Param(name="aliasname", primary=true)
+ private String aliasName;
+
+ @Inject
+ private DomainScopedPasswordAliasStore domainPasswordAliasStore;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ try {
+ if ( ! domainPasswordAliasStore.containsKey(aliasName)) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.password.alias.notfound",
+ "Password alias for the alias {0} does not exist.",
+ aliasName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ } catch (Exception ex) {
+ reportFailure(context.getActionReport(), ex);
+ return false;
+ }
+ return true;
+ }
+
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ try {
+ domainPasswordAliasStore.remove(aliasName);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ reportFailure(report, ex);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ /*report.setMessage(localStrings.getLocalString(
+ "delete.password.alias.success",
+ "Password alias for the alias {0} deleted successfully",
+ aliasName));*/
+ }
+
+ private void reportFailure(final ActionReport report,
+ final Exception ex) {
+ report.setMessage(localStrings.getLocalString(
+ "delete.password.alias.fail",
+ "Deletion of Password Alias {0} failed", aliasName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(ex);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuditModule.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuditModule.java
new file mode 100644
index 0000000..897b840
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuditModule.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuditModule;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * List Audit Modules Command
+ * Usage: list-audit-modules [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s]
+ * [--user admin_user] [--passwordfile file_name] [target(Default server)]
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-audit-modules")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.audit.module")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.CLUSTERED_INSTANCE,
+CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-audit-modules",
+ description="List Audit Modules")
+})
+public class ListAuditModule implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListAuditModule.class);
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.To(value="read")
+ private SecurityService securityService = null;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ securityService = chooseSecurityService(context.getActionReport());
+ return true;
+ }
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ report.getTopMessagePart().setChildrenType("audit-module");
+ for (AuditModule am : securityService.getAuditModule()) {
+ ActionReport.MessagePart part = report.getTopMessagePart().addChild();
+ part.setMessage(am.getName());
+ }
+ }
+
+ private SecurityService chooseSecurityService(final ActionReport report) {
+ config = CLIUtil.chooseConfig(domain, target, report);
+ if (config == null) {
+ return null;
+ }
+ return config.getSecurityService();
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuthRealm.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuthRealm.java
new file mode 100644
index 0000000..56e834b
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListAuthRealm.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+
+
+
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+
+/**
+ * List Auth Realms Command
+ * Usage: list-auth-realms [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s]
+ * [--user admin_user] [--passwordfile file_name] [target(Default server)]
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-auth-realms")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.auth.realm")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,
+CommandTarget.CLUSTER, CommandTarget.CONFIG,CommandTarget.CLUSTERED_INSTANCE})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-auth-realms",
+ description="List Auth Realms")
+})
+public class ListAuthRealm implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListAuthRealm.class);
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+ @Inject
+ private RealmsManager realmsManager;
+
+ @AccessRequired.To("read")
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ return true;
+ }
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+// Enumeration realms = Realm.getRealmNames();
+//
+// if ( realms == null || !realms.hasMoreElements()) {
+// //Create realms
+// realmsManager.createRealms(securityService);
+// }
+
+ for (AuthRealm authRealm : securityService.getAuthRealm()) {
+ ActionReport.MessagePart part = report.getTopMessagePart().addChild();
+ part.setMessage(authRealm.getName());
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileGroup.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileGroup.java
new file mode 100644
index 0000000..70af683
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileGroup.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import java.util.Enumeration;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * List File GroupsCommand
+ * Usage: list-file-groups [--terse={true|false}][ --echo={true|false} ]
+ * [ --interactive={true|false} ] [--host host] [--port port]
+ * [--secure| -s ] [--user admin_user] [--passwordfile filename]
+ * [--help] [--name username] [--authrealmname auth_realm_name] [ target]
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-file-groups")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.file.group")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,
+CommandTarget.CLUSTERED_INSTANCE, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-file-groups",
+ description="list-file-groups")
+})
+public class ListFileGroup implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListFileGroup.class);
+
+ @Param(name="authrealmname", optional=true)
+ private String authRealmName;
+
+ @Param(name="name", optional=true)
+ private String fileUserName;
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Configs configs;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @AccessRequired.To("read")
+ private AuthRealm fileAuthRealm;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ fileAuthRealm = CLIUtil.findRealm(securityService, authRealmName);
+ if (fileAuthRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "list.file.group.filerealmnotfound",
+ "File realm {0} does not exist", authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ /*
+ * The realm might have been defaulted, so capture the actual name.
+ */
+ authRealmName = fileAuthRealm.getName();
+ return true;
+ }
+
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ try {
+ // Get all users of this file realm. If a username has
+ // been passed in through the --name CLI option use that
+ FileRealm fr = getFileRealm(securityService, fileAuthRealm, report);
+
+ if (fr == null) {
+ // the getFileRealm method would have filled
+ // in the right cause of this situation
+ return;
+ }
+
+ Enumeration groups = null;
+ if (fileUserName != null) {
+ fr.getUser(fileUserName);
+ groups = fr.getGroupNames(fileUserName);
+ } else {
+ groups = fr.getGroupNames();
+ }
+
+ report.getTopMessagePart().setMessage(localStrings.getLocalString(
+ "list.file.group.success",
+ "list-file-groups successful"));
+ report.getTopMessagePart().setChildrenType("file-group");
+ while (groups.hasMoreElements()) {
+ final ActionReport.MessagePart part =
+ report.getTopMessagePart().addChild();
+ part.setMessage((String) groups.nextElement());
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (BadRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.group.realmcorrupted",
+ "Configured file realm {0} is corrupted.", authRealmName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ } catch (NoSuchUserException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.group.usernotfound",
+ "Specified file user {0} not found.", fileUserName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+
+ private FileRealm getFileRealm(final SecurityService securityService, AuthRealm fileAuthRealm, ActionReport report) {
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.",
+ fileRealmClassName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return null;
+ }
+
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString("list.file.user.keyfilenotfound",
+ "There is no physical file associated with this file realm {0} ",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return null;
+ }
+
+ // We have the right impl so let's try to remove one
+ FileRealm fr = null;
+ try {
+ realmsManager.createRealms(config);
+ fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(),authRealmName);
+ if (fr == null) {
+ throw new NoSuchRealmException(authRealmName);
+ }
+ } catch(NoSuchRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.", authRealmName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ return fr;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileUser.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileUser.java
new file mode 100644
index 0000000..bf34baa
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListFileUser.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.security.auth.realm.NoSuchUserException;
+import java.util.Enumeration;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.BadRealmException;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.io.File;
+import org.glassfish.api.admin.ExecuteOn;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * List File Users Command
+ * Usage: list-file-users [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s] [--user admin_user]
+ * [--passwordfile file_name] [--authrealmname authrealm_name]
+ * [target(Default server)]
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-file-users")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.file.user")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER,
+ CommandTarget.CLUSTERED_INSTANCE,CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=AuthRealm.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-users",
+ description="List Users",
+ params={
+ @RestParam(name="authrealmname", value="$parent")
+ })
+})
+public class ListFileUser implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListFileUser.class);
+
+ @Param(name="authrealmname", optional=true)
+ private String authRealmName;
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @AccessRequired.To("read")
+ private AuthRealm fileAuthRealm;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ fileAuthRealm = CLIUtil.findRealm(securityService, authRealmName);
+ if (fileAuthRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "list.file.user.filerealmnotfound",
+ "File realm {0} does not exist", authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ /*
+ * The realm might have been defaulted, so capture the actual name.
+ */
+ authRealmName = fileAuthRealm.getName();
+ return true;
+ }
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.",
+ fileRealmClassName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString("list.file.user.keyfilenotfound",
+ "There is no physical file associated with this file realm {0} ",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ boolean exists = (new File(keyFile)).exists();
+ if (!exists) {
+ report.setMessage(
+ localStrings.getLocalString("file.realm.keyfilenonexistent",
+ "The specified physical file {0} associated with the file realm {1} does not exist.",
+ new Object[]{keyFile, authRealmName}));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ // We have the right impl so let's try to remove one
+ FileRealm fr = null;
+ try {
+ realmsManager.createRealms(config);
+ //account for updates to realms from outside this config sharing
+ //same keyfile
+ CreateFileUser.refreshRealm(config.getName(), authRealmName);
+ fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(),authRealmName);
+ if (fr == null) {
+ throw new NoSuchRealmException(authRealmName);
+ }
+ } catch(NoSuchRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.", authRealmName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+
+ try {
+ Enumeration users = fr.getUserNames();
+ List userList = new ArrayList();
+
+ while (users.hasMoreElements()) {
+ final ActionReport.MessagePart part = report.getTopMessagePart().addChild();
+ String userName = (String) users.nextElement();
+ part.setMessage(userName);
+ Map userMap = new HashMap();
+ userMap.put("name", userName);
+ try {
+ userMap.put("groups", Collections.list(fr.getGroupNames(userName)));
+ } catch (NoSuchUserException ex) {
+ // This should never be thrown since we just got the user name from the realm
+ }
+ userList.add(userMap);
+ }
+ Properties extraProperties = new Properties();
+ extraProperties.put("users", userList);
+ report.setExtraProperties(extraProperties);
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (BadRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "list.file.user.realmcorrupted",
+ "Configured file realm {0} is corrupted.", authRealmName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListJaccProviders.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListJaccProviders.java
new file mode 100644
index 0000000..8e26d15
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListJaccProviders.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.JaccProvider;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.util.List;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+ *Usage: list-jacc-providers
+ * [--help] [--user admin_user] [--passwordfile file_name]
+ * [target(Default server)]
+ *
+ */
+@Service(name="list-jacc-providers")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.jacc.provider")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.CLUSTERED_INSTANCE,
+CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-jacc-providers",
+ description="list-jacc-providers")
+})
+public class ListJaccProviders implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(DeleteJaccProvider.class);
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Configs configs;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.To("read")
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ config = CLIUtil.chooseConfig(domain, target, report);
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ return true;
+ }
+
+
+
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ List<JaccProvider> jaccProviders = securityService.getJaccProvider();
+ JaccProvider jprov = null;
+ for (JaccProvider jaccProv : jaccProviders) {
+ ActionReport.MessagePart part = report.getTopMessagePart().addChild();
+ part.setMessage(jaccProv.getName());
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListMessageSecurityProvider.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListMessageSecurityProvider.java
new file mode 100644
index 0000000..3ebbf47
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListMessageSecurityProvider.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.MessageSecurityConfig;
+import com.sun.enterprise.config.serverbeans.ProviderConfig;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+/**
+ * List Message Security Providers Command
+ *
+ * Usage: list-message-security-providers [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ * [--layer message_layer] [target(Default server)]
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-message-security-providers")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.message.security.provider")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.CLUSTERED_INSTANCE,
+CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-message-security-providers",
+ description="list-message-security-providers")
+})
+public class ListMessageSecurityProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListMessageSecurityProvider.class);
+
+ @Param(name = "target", primary=true, optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+ // auth-layer can only be SOAP | HttpServlet
+ @Param(name="layer", acceptableValues="SOAP,HttpServlet", optional=true)
+ String authLayer;
+
+ @AccessRequired.To("read")
+ private SecurityService secService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ secService = config.getSecurityService();
+ return true;
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ secService.getMessageSecurityConfig();
+
+ report.getTopMessagePart().setMessage(
+ localStrings.getLocalString(
+ "list.message.security.provider.success",
+ "list-message-security-providers successful"));
+ report.getTopMessagePart().setChildrenType("");
+
+ for (MessageSecurityConfig msc : secService.getMessageSecurityConfig()) {
+ if (authLayer == null) {
+ for (ProviderConfig pc : msc.getProviderConfig()) {
+ ActionReport.MessagePart part =
+ report.getTopMessagePart().addChild();
+ part.setMessage(pc.getProviderId());
+ }
+ } else {
+ if (msc.getAuthLayer().equals(authLayer)) {
+ for (ProviderConfig pc : msc.getProviderConfig()) {
+ ActionReport.MessagePart part =
+ report.getTopMessagePart().addChild();
+ part.setMessage(pc.getProviderId());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListPasswordAlias.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListPasswordAlias.java
new file mode 100644
index 0000000..5e42c4d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListPasswordAlias.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import java.util.Iterator;
+import org.glassfish.api.admin.AccessRequired;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.CommandLock;
+import org.glassfish.api.I18n;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+
+/**
+ * List Password Aliases Command
+ *
+ * Usage: list-password-aliases [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name]
+ *
+ * Result of the command is that:
+ * <domain-dir>/<domain-name>/config/domain-passwords file gets appended with
+ * the entry of the form: aliasname=<password encrypted with masterpassword>
+ *
+ * A user can use this aliased password now in setting passwords in domin.xml.
+ * Benefit is it is in NON-CLEAR-TEXT
+ *
+ * domain.xml example entry is:
+ * <provider-config class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule"
+ * provider-id="XWS_ClientProvider" provider-type="client">
+ * <property name="password" value="${ALIAS=myalias}/>
+ * </provider-config>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="list-password-aliases")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.password.alias")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.DOMAIN})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-password-aliases",
+ description="list-password-aliases")
+})
+@AccessRequired(resource="domain/passwordAliases", action="read")
+public class ListPasswordAlias implements AdminCommand {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListPasswordAlias.class);
+
+ @Inject
+ private DomainScopedPasswordAliasStore domainPasswordAliasStore;
+
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ try {
+ final Iterator<String> it = domainPasswordAliasStore.keys();
+
+ if (! it.hasNext()) {
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ report.setMessage(localStrings.getLocalString(
+ "list.password.alias.nothingtolist",
+ "Nothing to list"));
+ }
+
+ while (it.hasNext()) {
+ ActionReport.MessagePart part =
+ report.getTopMessagePart().addChild();
+ part.setMessage(it.next());
+ }
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ report.setMessage(localStrings.getLocalString(
+ "list.password.alias.fail", "Listing of Password Alias failed"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(ex);
+ return;
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListSupportedCipherSuites.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListSupportedCipherSuites.java
new file mode 100644
index 0000000..51d59bc
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/ListSupportedCipherSuites.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.ssl.SSLUtils;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+
+/**
+ * author - Nithya Subramanian
+ *
+ * Usage: list-supported-cipher-suites
+ * [--help] [--user admin_user] [--passwordfile file_name]
+ * [target_name(default server)]
+ **/
+
+@Service(name = "list-supported-cipher-suites")
+@PerLookup
+@CommandLock(CommandLock.LockType.NONE)
+@I18n("list.supported.cipher.suites")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS, CommandTarget.STANDALONE_INSTANCE, CommandTarget.CLUSTERED_INSTANCE})
+@RestEndpoints({
+ @RestEndpoint(configBean=SecurityService.class,
+ opType=RestEndpoint.OpType.GET,
+ path="list-supported-cipher-suites",
+ description="List Supported Cipher Suites")
+})
+@AccessRequired(resource="domain/security-service", action="read")
+public class ListSupportedCipherSuites implements AdminCommand {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(ListSupportedCipherSuites.class);
+ @Inject
+ SSLUtils sslutils;
+
+ /*@Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;*/
+ @Param(optional = true, primary = true, defaultValue = SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ String[] cipherSuites = sslutils.getSupportedCipherSuites();
+
+ for (String cipherSuite : cipherSuites) {
+ if (!cipherSuite.contains("_KRB5_")) {
+ ActionReport.MessagePart part = report.getTopMessagePart().addChild();
+ part.setMessage(cipherSuite);
+ }
+ }
+
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/LocalStrings.properties
new file mode 100644
index 0000000..248681d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/LocalStrings.properties
@@ -0,0 +1,100 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+file.realm.keyfilenonexistent=The specified physical file {0} associated with the file realm {1} does not exist.
+create.file.user.usagetext=create-file-user\n\t[--authrealmname <authrealm_name>] [--target target] \n\t[--groups user_groups[:user_groups]*] \n\t[-?|--help[=<help(default:false)>]] username
+create.file.user.filerealmnotfound=File realm {0} does not exist
+create.file.user.keyfilenotfound=No physical file is associated with file realm {0}.
+create.file.user.keyfilenotreadable=None of password or groups have been specified for update, Password for user {0} has to be specified through AS_ADMIN_USERPASSWORD property in the file specified in --passwordfile option.
+create.file.user.realmnotsupported=Configured file realm {0} is not supported.
+create.file.user.realmcorrupted=Configured file realm {0} is corrupted.
+create.file.user.useraddfailed=Adding User {0} to file realm {1} failed.
+create.file.user.userpassword=The user password
+create.file.user.userpassword.prompt=Enter the user password
+create.file.user.userpassword.promptAgain=Enter the user password again
+delete.file.user.filerealmnotfound=File realm {0} does not exist
+delete.file.user.keyfilenotfound=No physical file is associated with the file realm {0}.
+delete.file.user.realmnotsupported=Configured file realm {0} is not supported.
+delete.file.user.realmcorrupted=Configured file realm {0} is corrupted.
+delete.file.user.userdeletefailed=Removing User {0} from file realm {0} failed.
+delete.file.user.usernotfound=User {0} does not exist in file realm {1}.
+delete.file.user.success=delete-file-user Successful.
+update.file.user.filerealmnotfound=File realm {0} does not exist.
+update.file.user.keyfilenotfound=No physical file associated with this file realm {0}.
+update.file.user.keyfilenotreadable=Password for user {0} has to be specified in --userpassword option or supplied through AS_ADMIN_USERPASSWORD property in the file specified in --passwordfile option.
+update.file.user.realmcorrupted=Configured file realm {0} is corrupted.
+update.file.user.realmnotsupported=Configured file realm {0} is not supported.
+update.file.user.userupdatefailed=Updating user {0} in file realm {1} failed.
+update.file.user.success=update-file-user Successful.
+update.file.user.userpassword=The user password
+update.file.user.userpassword.prompt=Enter the user password
+update.file.user.userpassword.promptAgain=Enter the user password again
+list.file.user.filerealmnotfound=File realm {0} does not exist
+list.file.user.realmnotsupported=Configured file realm {0} is not supported.
+list.file.user.keyfilenotfound=There is no physical file associated with the file realm {0}
+list.file.user.realmcorrupted=Configured file realm {0} is corrupted.
+list.file.user.success=list-file-users Successful.
+create.user.ok.anon.allowed=A new ''admin user'' {0} is now created for immediate use, however, this domain still allows anonymous admin access. You should consider removing the admin user ''anonymous''.
+create.user.ok=A new ''admin user'' {0} is now created for immediate use
+
+create.auth.realm.duplicatefound=Authrealm named {0} exists. Cannot add duplicate Authrealm.
+create.auth.realm.fail=Creation of Authrealm {0} failed.
+create.auth.realm.success=Creation of Authrealm {0} completed successfully.
+delete.auth.realm.notfound=Authrealm named {0} not found.
+delete.auth.realm.fail=Deletion of Authrealm {0} failed.
+delete.auth.realm.success=Deletion of Authrealm {0} completed successfully.
+list.auth.realm.success=list-auth-realms Successful
+
+list.file.group.filerealmnotfound=File realm {0} does not exist
+list.file.group.success=list-file-groups Successful
+list.file.group.realmcorrupted=Configured file realm {0} is corrupted
+list.file.group.usernotfound=Specified file user {0} not found
+list.file.group.realmnotsupported=Configured file realm {0} is not supported
+list.file.group.keyfilenotfound=There is no physical file associated with this file realm {0}
+
+change.admin.password.adminrealmnotfound=There is no admin realm to perform this operation.
+change.admin.password.adminrealmnotsupported=Configured admin realm is not of supported type.
+change.admin.password.keyfilenotfound=There is no physical file associated with admin realm.
+change.admin.password.realmcorrupted=Configured admin realm is corrupted.
+change.admin.password.realmnotsupported=Configured admin realm does not exist.
+change.admin.password.userupdatefailed=Password change failed for user named {0}.
+
+create.password.alias.fail=Creation of Password Alias {0} failed
+create.password.alias.success=Encrypted password for the alias name {0} stored successfully
+create.password.alias.aliaspassword=The alias password
+create.password.alias.aliaspassword.prompt=Enter the alias password
+create.password.alias.aliaspassword.promptAgain=Enter the alias password again
+list.password.alias.fail=Listing of Password Alias failed
+list.password.alias.success=List password aliases executed successfully
+list.password.alias.nothingtolist=Nothing to list
+delete.password.alias.success=Password alias for the alias {0} deleted successfully
+delete.password.alias.fail=Deletion of Password Alias {0} failed
+delete.password.alias.notfound=Password alias for the alias {0} does not exist.
+update.password.alias.notfound=Password alias for the alias {0} does not exist.
+update.password.alias.fail=Update of Password Alias {0} failed
+update.password.alias.success=Encrypted password for the alias {0} updated successfully
+update.password.alias.aliaspassword=The alias password
+update.password.alias.aliaspassword.prompt=Enter the alias password
+update.password.alias.aliaspassword.promptAgain=Enter the alias password again
+#realm.not.refreshed=Admin auth realm could not be refreshed. Please restart the server.
+create.password.alias.alreadyexists=Password alias with the specified name already exists. Please use the update-password-alias command to change it
+#create-jacc-provider
+create.jacc.provider.duplicatefound=JaccProvider named {0} exists. Cannot add duplicate JaccProvider.
+delete.jacc.provider.notfound=JaccProvider named {0} not found.
+delete.jacc.provider.fail=Deletion of JaccProvider {0} failed.
+delete.jacc.provider.notallowed=JaccProvider named {0} is a system provider and cannot be deleted.
+
+util.noconfigfortarget=Configuration for target {0} not found.
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdateFileUser.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdateFileUser.java
new file mode 100644
index 0000000..b7db42d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdateFileUser.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.AdminService;
+import java.util.List;
+
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.types.Property;
+import com.sun.enterprise.config.serverbeans.Config;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.Configs;
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.security.auth.realm.file.FileRealm;
+import com.sun.enterprise.security.auth.realm.NoSuchRealmException;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.config.serverbeans.Server;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.io.File;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+/**
+ * Update File User Command
+ *
+ * Usage: update-file-user [--terse=false] [--echo=false] [--interactive=true]
+ * [--host localhost] [--port 4848|4849] [--secure | -s] [--user admin_user]
+ * [--passwordfile file_name] [--userpassword admin_passwd]
+ * [--groups user_groups[:user_groups]*] [--authrealmname authrealm_name]
+ * [--target target(Default server)] username
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="update-file-user")
+@PerLookup
+@I18n("update.file.user")
+@ExecuteOn({RuntimeType.ALL})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=AuthRealm.class,
+ opType=RestEndpoint.OpType.POST,
+ path="update-user",
+ description="Update Users",
+ params={
+ @RestParam(name="authrealmname", value="$parent")
+ })
+})
+public class UpdateFileUser implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(UpdateFileUser.class);
+
+ @Param(name="groups", optional=true, separator=':')
+ private List<String> groups = null;
+
+ // @Param(name="userpasswordfile", optional=true)
+ // String passwordFile;
+
+ @Param(name="userpassword", optional=true, password=true)
+ private String userpassword;
+
+ @Param(name="authrealmname", optional=true)
+ private String authRealmName;
+
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ @Param(name="username", primary=true)
+ private String userName;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private Config config;
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private RealmsManager realmsManager;
+
+ @Inject
+ private AdminService adminService;
+
+ private SecureAdmin secureAdmin = null;
+
+ @AccessRequired.To("update")
+ private AuthRealm fileAuthRealm;
+
+ private SecurityService securityService;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ config = CLIUtil.chooseConfig(domain, target, context.getActionReport());
+ if (config == null) {
+ return false;
+ }
+ securityService = config.getSecurityService();
+ fileAuthRealm = CLIUtil.findRealm(securityService, authRealmName);
+ if (fileAuthRealm == null) {
+ final ActionReport report = context.getActionReport();
+ report.setMessage(localStrings.getLocalString(
+ "update.file.user.filerealmnotfound",
+ "File realm {0} does not exist",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ /*
+ * The realm might have been defaulted, so capture the actual name.
+ */
+ authRealmName = fileAuthRealm.getName();
+ return true;
+ }
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are the paramter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+
+ final ActionReport report = context.getActionReport();
+
+ // Get FileRealm class name, match it with what is expected.
+ String fileRealmClassName = fileAuthRealm.getClassname();
+
+ // Report error if provided impl is not the one expected
+ if (fileRealmClassName != null &&
+ !fileRealmClassName.equals(
+ "com.sun.enterprise.security.auth.realm.file.FileRealm")) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "update.file.user.realmnotsupported",
+ "Configured file realm {0} is not supported.",
+ fileRealmClassName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // ensure we have the file associated with the authrealm
+ String keyFile = null;
+ for (Property fileProp : fileAuthRealm.getProperty()) {
+ if (fileProp.getName().equals("file"))
+ keyFile = fileProp.getValue();
+ }
+ if (keyFile == null) {
+ report.setMessage(
+ localStrings.getLocalString("update.file.user.keyfilenotfound",
+ "There is no physical file associated with file realm {0}",
+ authRealmName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ boolean exists = (new File(keyFile)).exists();
+ if (!exists) {
+ report.setMessage(
+ localStrings.getLocalString("file.realm.keyfilenonexistent",
+ "The specified physical file {0} associated with the file realm {1} does not exist.",
+ new Object[]{keyFile, authRealmName}));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // Now get all inputs ready. userid and groups are straightforward but
+ // password is tricky. It is stored in the file passwordfile passed
+ // through the CLI options. It is stored under the name
+ // AS_ADMIN_USERPASSWORD. Fetch it from there.
+ String password = userpassword; // fetchPassword(report);
+ if (password == null && groups == null) {
+ report.setMessage(localStrings.getLocalString(
+ "update.file.user.keyfilenotreadable", "None of password or groups have been specified for update,"
+ + "Password for user {0} has to be specified"
+ + "through AS_ADMIN_USERPASSWORD property in the file specified "
+ + "in --passwordfile option", userName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ //Issue 17525 Fix - Check for null passwords for admin-realm if secureadmin is enabled
+ if (password != null) {
+ secureAdmin = domain.getSecureAdmin();
+ if ((SecureAdmin.Util.isEnabled(secureAdmin))
+ && (adminService.getAuthRealmName().equals(authRealmName))) {
+ if ((password.isEmpty())) {
+ report.setMessage(localStrings.getLocalString(
+ "null_empty_password", "The admin user password is empty"));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ }
+ }
+
+ //even though update-file-user is not an update to the security-service
+ //do we need to make it transactional by referncing the securityservice
+ //hypothetically ?.
+ //TODO: check and enclose the code below inside ConfigSupport.apply(...)
+ FileRealm fr = null;
+ try {
+ realmsManager.createRealms(config);
+ fr = (FileRealm) realmsManager.getFromLoadedRealms(config.getName(),authRealmName);
+ if (fr == null) {
+ throw new NoSuchRealmException(authRealmName);
+ }
+ } catch(NoSuchRealmException e) {
+ report.setMessage(
+ localStrings.getLocalString(
+ "update.file.user.realmnotsupported",
+ "Configured file realm {0} does not exist.", authRealmName) +
+ " " + e.getLocalizedMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ return;
+ }
+
+ //now updating user
+ try {
+ CreateFileUser.handleAdminGroup(authRealmName, groups);
+ String[] groups1 = (groups == null) ? null: groups.toArray(new String[groups.size()]);
+ fr.updateUser(userName, userName, password, groups1);
+ fr.persist();
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch (Exception e) {
+ report.setMessage(
+ localStrings.getLocalString("update.file.user.userupdatefailed",
+ "Updating user {0} in file realm {1} failed",
+ userName, authRealmName) + " " + e.getLocalizedMessage() );
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(e);
+ }
+ }
+
+ /* private String fetchPassword(ActionReport report) {
+ String password = null;
+ if (userpassword != null && passwordFile != null)
+ return password;
+ if (userpassword != null)
+ password = userpassword;
+ if (passwordFile != null) {
+ File passwdFile = new File(passwordFile);
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(passwdFile));
+ Properties prop = new Properties();
+ prop.load(is);
+ for (Enumeration e=prop.propertyNames(); e.hasMoreElements();) {
+ String entry = (String)e.nextElement();
+ if (entry.equals("AS_ADMIN_USERPASSWORD")) {
+ password = prop.getProperty(entry);
+ break;
+ }
+ }
+ } catch(Exception e) {
+ report.setFailureCause(e);
+ } finally {
+ try {
+ if (is != null)
+ is.close();
+ } catch(final Exception ignore){}
+ }
+ }
+ return password;
+ } */
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdatePasswordAlias.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdatePasswordAlias.java
new file mode 100644
index 0000000..99264a2
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/cli/UpdatePasswordAlias.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.cli;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.I18n;
+import org.glassfish.api.Param;
+import org.glassfish.api.ActionReport;
+import org.jvnet.hk2.annotations.Service;
+
+import org.glassfish.hk2.api.PerLookup;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import javax.inject.Inject;
+
+/**
+ * Update Password Alias Command
+ *
+ * Usage: update-password-alias [--terse=false] [--echo=false]
+ * [--interactive=true] [--host localhost] [--port 4848|4849]
+ * [--secure | -s] [--user admin_user] [--passwordfile file_name] aliasname
+ *
+ * Result of the command is that:
+ * the entry of the form: aliasname=<password-encrypted-with-masterpassword> in
+ * <domain-dir>/<domain-name>/config/domain-passwords file gets updated with the
+ * new alias password
+ *
+ * domain.xml example entry is:
+ * <provider-config class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule"
+ * provider-id="XWS_ClientProvider" provider-type="client">
+ * <property name="password" value="${ALIAS=myalias}/>
+ * </provider-config>
+ *
+ * @author Nandini Ektare
+ */
+
+@Service(name="update-password-alias")
+@PerLookup
+@I18n("update.password.alias")
+@ExecuteOn({RuntimeType.DAS})
+@TargetType({CommandTarget.DAS,CommandTarget.DOMAIN})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST,
+ path="update-password-alias",
+ description="update-password-alias")
+})
+@AccessRequired(resource="domain/passwordAliases/passwordAlias/$aliasName", action="update")
+public class UpdatePasswordAlias implements AdminCommand {
+
+ final private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(CreatePasswordAlias.class);
+
+ @Param(name="aliasname", primary=true)
+ private String aliasName;
+
+ @Param(name="aliaspassword", password=true)
+ private String aliasPassword;
+
+ @Inject
+ private DomainScopedPasswordAliasStore domainPasswordAliasStore;
+
+ /**
+ * Executes the command with the command parameters passed as Properties
+ * where the keys are parameter names and the values the parameter values
+ *
+ * @param context information
+ */
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ try {
+ if ( ! domainPasswordAliasStore.containsKey(aliasName)) {
+ report.setMessage(localStrings.getLocalString(
+ "update.password.alias.notfound",
+ "Password alias for the alias {0} does not exist.",
+ aliasName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ domainPasswordAliasStore.put(aliasName, aliasPassword.toCharArray());
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ report.setMessage(localStrings.getLocalString(
+ "update.password.alias.fail",
+ "Update of Password Alias {0} failed", aliasName));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(ex);
+ return;
+ }
+ report.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ report.setMessage(localStrings.getLocalString(
+ "update.password.alias.success",
+ "Encrypted password for the alias {0} updated successfully",
+ aliasName));
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AbstractSecurityContext.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AbstractSecurityContext.java
new file mode 100644
index 0000000..16e012d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AbstractSecurityContext.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+import com.sun.enterprise.security.integration.AppServSecurityContext;
+import java.security.Principal;
+import javax.security.auth.Subject;
+
+/**
+ * This base class defines the methods that Security Context should exhibit.
+ * There are two places where a derived class are used. They are on the
+ * appclient side and ejb side. The derived classes can use thread local
+ * storage to store the security contexts.
+ *
+ * @author Harpreet Singh
+ */
+public abstract class AbstractSecurityContext implements AppServSecurityContext, java.io.Serializable {
+ // the principal that this security context represents.
+ protected Principal initiator = null;
+ protected Subject subject = null;
+
+ /**
+ * This method should be implemented by the subclasses to
+ * return the caller principal. This information may be redundant
+ * since the same information can be inferred by inspecting the
+ * Credentials of the caller.
+ * @return The caller Principal.
+ */
+ abstract public Principal getCallerPrincipal();
+
+ /**
+ * This method should be implemented by the subclasses to return
+ * the Credentials of the caller principal.
+ * @return A credentials object associated with the current client
+ * invocation.
+ */
+ abstract public Subject getSubject();
+}
+
+
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AppservAccessController.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AppservAccessController.java
new file mode 100644
index 0000000..12b481c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/AppservAccessController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class provides an optimization for some methods in
+ * java.security.AccessController.
+ * @author Shing Wai Chan
+ */
+public final class AppservAccessController {
+ private static boolean isSecMgrOff = (System.getSecurityManager() == null);
+
+ private AppservAccessController() {
+ }
+
+ public static Object doPrivileged(PrivilegedAction action) {
+ if (isSecMgrOff) {
+ return action.run();
+ } else {
+ return AccessController.doPrivileged(action);
+ }
+ }
+
+ public static Object doPrivileged(PrivilegedExceptionAction action)
+ throws PrivilegedActionException {
+
+ if (isSecMgrOff) {
+ try {
+ return action.run();
+ } catch(Exception e) {
+ throw new PrivilegedActionException(e);
+ }
+ } else {
+ return AccessController.doPrivileged(action);
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/ClientSecurityContext.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/ClientSecurityContext.java
new file mode 100644
index 0000000..7a6ec68
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/ClientSecurityContext.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.integration.AppServSecurityContext;
+import java.security.Principal;
+import javax.security.auth.Subject;
+
+import org.glassfish.security.common.PrincipalImpl;
+//V3:Comment import com.sun.enterprise.ServerConfiguration;
+
+import java.util.logging.*;
+import com.sun.logging.*;
+
+
+/**
+ * This class represents the security context on the client side.
+ * For usage of the IIOP_CLIENT_PER_THREAD_FLAG flag, see
+ * UsernamePasswordStore. When set to false, the volatile
+ * field sharedCsc is used to store the context.
+ *
+ * @see UsernamePasswordStore
+ * @author Harpreet Singh
+ *
+ */
+public final class ClientSecurityContext extends AbstractSecurityContext {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ public static final String IIOP_CLIENT_PER_THREAD_FLAG =
+ "com.sun.appserv.iiopclient.perthreadauth";
+
+ // Bug Id: 4787940
+ private static final boolean isPerThreadAuth =
+ Boolean.getBoolean(IIOP_CLIENT_PER_THREAD_FLAG);
+
+ // either the thread local or shared version will be used
+ private static ThreadLocal localCsc =
+ isPerThreadAuth ? new ThreadLocal() : null;
+ private static volatile ClientSecurityContext sharedCsc;
+
+ /**
+ * This creates a new ClientSecurityContext object.
+ * @param The name of the user.
+ * @param The Credentials of the user.
+ */
+ public ClientSecurityContext(String userName,
+ Subject s) {
+
+ this.initiator = new PrincipalImpl(userName);
+ this.subject = s ;
+ }
+
+ /**
+ * Initialize the SecurityContext & handle the unauthenticated
+ * principal case
+
+ public static ClientSecurityContext init() {
+ ClientSecurityContext sc = getCurrent();
+ if (sc == null) { // there is no current security context
+ // create a default one if
+ sc = generateDefaultSecurityContext();
+ }
+ return sc;
+ }*/
+
+ /*
+ private static ClientSecurityContext generateDefaultSecurityContext() {
+ final String PRINCIPAL_NAME = "auth.default.principal.name";
+ final String PRINCIPAL_PASS = "auth.default.principal.password";
+
+
+ //ServerConfiguration config = ServerConfiguration.getConfiguration();
+ //String username = config.getProperty(PRINCIPAL_NAME, "guest");
+ //String password = config.getProperty(PRINCIPAL_PASS, "guest123");
+
+ //Temporary hardcoding to make V3 code for WebProfile compile
+ String username ="guest";
+ char[] password = new char[]{'g','e','t','s','t','1','2','3'};
+ synchronized (ClientSecurityContext.class) {
+ // login & all that stuff..
+ try {
+ final Subject subject = new Subject();
+ final PasswordCredential pc = new PasswordCredential(username,
+ password, "default");
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ subject.getPrivateCredentials().add(pc);
+ return null;
+ }
+ });
+ // we do not need to generate any credential as authorization
+ // decisions are not being done on the appclient side.
+ ClientSecurityContext defaultCSC =
+ new ClientSecurityContext(username, subject);
+ setCurrent(defaultCSC);
+ return defaultCSC;
+ } catch(Exception e) {
+ _logger.log(Level.SEVERE,
+ "java_security.gen_security_context", e);
+ return null;
+ }
+ }
+ }
+ */
+
+ /**
+ * This method gets the SecurityContext stored here. If using a
+ * per-thread authentication model, it gets the context from
+ * Thread Local Store (TLS) of the current thread. If not using a
+ * per-thread authentication model, it gets the singleton context.
+ *
+ * @return The current Security Context stored here. It returns
+ * null if SecurityContext could not be found.
+ */
+ public static ClientSecurityContext getCurrent() {
+ if (isPerThreadAuth) {
+ return (ClientSecurityContext) localCsc.get();
+ } else {
+ return sharedCsc;
+ }
+ }
+
+ /**
+ * This method sets the SecurityContext to be stored here.
+ *
+ * @param The Security Context that should be stored.
+ */
+ public static void setCurrent(ClientSecurityContext sc) {
+ if (isPerThreadAuth) {
+ localCsc.set(sc);
+ } else {
+ sharedCsc = sc;
+ }
+ }
+
+ /**
+ * This method returns the caller principal.
+ * This information may be redundant since the same information
+ * can be inferred by inspecting the Credentials of the caller.
+ *
+ * @return The caller Principal.
+ */
+ public Principal getCallerPrincipal() {
+ return initiator;
+ }
+
+
+ public Subject getSubject() {
+ return subject;
+ }
+
+ public String toString() {
+ return "ClientSecurityContext[ " + "Initiator: " + initiator +
+ "Subject " + subject + " ]";
+ }
+
+ //added for CR:6620388
+ public static boolean hasEmtpyCredentials(ClientSecurityContext sc) {
+ if (sc == null) {
+ return true;
+ }
+ Subject s = sc.getSubject();
+ if (s == null) {
+ return true;
+ }
+ if (s.getPrincipals().isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ public AppServSecurityContext newInstance(String userName, Subject subject, String realm) {
+ //TODO:V3 ignoring realm in this case
+ return new ClientSecurityContext(userName, subject);
+ }
+
+ public AppServSecurityContext newInstance(String userName, Subject subject) {
+ return new ClientSecurityContext(userName, subject);
+ }
+
+ public void setCurrentSecurityContext(AppServSecurityContext context) {
+ if (context instanceof ClientSecurityContext) {
+ setCurrent((ClientSecurityContext)context);
+ return;
+ }
+ throw new IllegalArgumentException("Expected ClientSecurityContext, found " + context);
+ }
+
+ public AppServSecurityContext getCurrentSecurityContext() {
+ return getCurrent();
+ }
+
+ public void setUnauthenticatedSecurityContext() {
+ throw new UnsupportedOperationException("Not supported yet in V3.");
+ }
+
+ public void setSecurityContextWithPrincipal(Principal principal) {
+ throw new UnsupportedOperationException("Not supported yet in V3.");
+ }
+
+
+}
+
+
+
+
+
+
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java
new file mode 100644
index 0000000..58f3096
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.EmbeddedSecurity;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.server.pluggable.SecuritySupport;
+import com.sun.enterprise.util.io.FileUtils;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.internal.embedded.EmbeddedFileSystem;
+import org.glassfish.internal.embedded.EmbeddedLifecycle;
+import org.glassfish.internal.embedded.Server;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ *
+ * @author Nithya Subramanian
+ */
+
+@Service
+public class EmbeddedSecurityLifeCycle
+ implements EmbeddedLifecycle{
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ @Inject
+ private EmbeddedSecurity embeddedSecurity;
+
+ @Inject @Named(ServerEnvironment.DEFAULT_INSTANCE_NAME)
+ private SecurityService securityService;
+
+ @Override
+ public void creation(Server server) {
+
+ //If the instanceRoot is not set to a non-embedded GF install,
+ //copy the security config files from the security.jar to the instanceRoot/config dir
+
+ EmbeddedFileSystem fileSystem = server.getFileSystem();
+ File instanceRoot = fileSystem.instanceRoot;
+ if (instanceRoot == null) {
+ return;
+ }
+
+ try {
+ //Get the keyfile names from the security service
+ List<String> keyFileNames = embeddedSecurity.getKeyFileNames(securityService);
+ for(String keyFileName:keyFileNames) {
+ //Copy the keyfiles in instanceRoot/config. If file is already present, then exit (handled by getManagedFile)
+ FileUtils.getManagedFile("config" + File.separator + embeddedSecurity.parseFileName(keyFileName), instanceRoot);
+ }
+ //Copy the other security files to instanceRoot/config
+ //Assuming that these files are present as config/filename in the embedded jar file and are to be extracted that way/
+ FileUtils.getManagedFile("config" + File.separator + "login.conf", instanceRoot);
+ FileUtils.getManagedFile("config" + File.separator + "server.policy", instanceRoot);
+ FileUtils.getManagedFile("config" + File.separator + "cacerts.jks", instanceRoot);
+ FileUtils.getManagedFile("config" + File.separator + "keystore.jks", instanceRoot);
+ String keystoreFile = null;
+ String truststoreFile = null;
+ try {
+ keystoreFile = Util.writeConfigFileToTempDir("keystore.jks").getAbsolutePath();
+ truststoreFile = Util.writeConfigFileToTempDir("cacerts.jks").getAbsolutePath();
+ } catch (IOException ex) {
+ _logger.log(Level.SEVERE, SecurityLoggerInfo.obtainingKeyAndTrustStoresError, ex);
+ }
+ System.setProperty(SecuritySupport.keyStoreProp, keystoreFile);
+ System.setProperty(SecuritySupport.trustStoreProp, truststoreFile);
+ }catch(IOException ioEx) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.copyingSecurityConfigFilesIOError, ioEx);
+ }
+ }
+
+ @Override
+ public void destruction(Server server) {
+
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/SecurityConstants.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/SecurityConstants.java
new file mode 100644
index 0000000..5c73baf
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/SecurityConstants.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+/**
+ *
+ * @author Kumar
+ */
+public interface SecurityConstants {
+
+ //copied from appclient.security to avoid dependency
+ public static final int USERNAME_PASSWORD = 1;
+ public static final int CERTIFICATE = 2;
+ // harry - added for LoginContextDriver access
+ public static final int ALL = 3;
+
+ public static final String CLIENT_JAAS_PASSWORD = "default";
+ public static final String CLIENT_JAAS_CERTIFICATE = "certificate";
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java
new file mode 100644
index 0000000..bd92d9f
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.common;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import javax.security.auth.callback.CallbackHandler;
+import org.glassfish.api.admin.ProcessEnvironment;
+import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.api.Globals;
+import org.glassfish.internal.embedded.Server;
+import javax.inject.Inject;
+
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Singleton;
+
+/**
+ *
+ * @author venu
+ * TODO: need to change this class, it needs to be similar to SecurityServicesUtil
+ */
+@Service
+@Singleton
+public class Util {
+ private static ServiceLocator habitat = Globals.getDefaultHabitat();
+
+ @Inject
+ private ProcessEnvironment penv;
+
+
+ //stuff required for AppClient
+ private CallbackHandler callbackHandler;
+ private Object appClientMsgSecConfigs;
+
+ //Note: Will return Non-Null only after Util has been
+ //Injected in some Service.
+ public static ServiceLocator getDefaultHabitat() {
+ return habitat;
+ }
+
+ public static Util getInstance() {
+ // return my singleton service
+ return habitat.getService(Util.class);
+ }
+
+ public boolean isACC() {
+ return penv.getProcessType().equals(ProcessType.ACC);
+ }
+ public boolean isServer() {
+ return penv.getProcessType().isServer();
+ }
+ public boolean isNotServerOrACC() {
+ return penv.getProcessType().equals(ProcessType.Other);
+ }
+
+ public CallbackHandler getCallbackHandler() {
+ return callbackHandler;
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+ public Object getAppClientMsgSecConfigs() {
+ return appClientMsgSecConfigs;
+ }
+
+ public void setAppClientMsgSecConfigs(Object appClientMsgSecConfigs) {
+ this.appClientMsgSecConfigs = appClientMsgSecConfigs;
+ }
+
+ public static boolean isEmbeddedServer() {
+ List<String> servers = Server.getServerNames();
+ if (!servers.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ public static File writeConfigFileToTempDir(String fileName) throws IOException {
+ File filePath = new File(fileName);
+
+ if (filePath.exists()) {
+ //the string provided is a filepath, so return
+ return filePath;
+ }
+ File localFile = null;
+ //Parent directories until the fileName exist, so create the file that has been provided
+ if (filePath.getParentFile() != null && filePath.getParentFile().exists()) {
+ localFile = filePath;
+ if(!localFile.createNewFile()) {
+ throw new IOException();
+ }
+
+ } else {
+ /*
+ * File parent directory does not exist - so create parent directory as user.home/.glassfish-{embedded}/config
+ * */
+ String userHome = System.getProperty("user.home");
+
+ String embeddedServerName = getCurrentEmbeddedServerName();
+ File tempDir = new File(userHome + File.separator + ".glassfish5-"+embeddedServerName+File.separator + "config");
+ boolean mkDirSuccess = true;
+ if (!tempDir.exists()) {
+ mkDirSuccess = tempDir.mkdirs();
+ }
+
+ localFile = new File(tempDir.getAbsolutePath()+File.separator + fileName);
+
+
+ if (mkDirSuccess && !localFile.exists()) {
+ localFile.createNewFile();
+ }
+ }
+ FileOutputStream oStream = null;
+ InputStream iStream = null;
+ try {
+ oStream = new FileOutputStream(localFile);
+ iStream = Util.class.getResourceAsStream("/config/" + fileName);
+
+ while (iStream != null && iStream.available() > 0) {
+ oStream.write(iStream.read());
+ }
+ } finally {
+ if (oStream != null) {
+ oStream.close();
+ }
+ if (iStream != null) {
+ iStream.close();
+ }
+
+ }
+
+ return localFile;
+
+ }
+
+ public static String getCurrentEmbeddedServerName() {
+ List<String> embeddedServerNames = Server.getServerNames();
+ String embeddedServerName = (embeddedServerNames.get(0) == null) ? "embedded" : embeddedServerNames.get(0);
+ return embeddedServerName;
+
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java
new file mode 100644
index 0000000..28a1f75
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.embedded;
+
+import com.sun.enterprise.config.serverbeans.AuthRealm;
+import com.sun.enterprise.config.serverbeans.SecurityService;
+import com.sun.enterprise.security.EmbeddedSecurity;
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.util.StringUtils;
+import com.sun.enterprise.util.io.FileUtils;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.server.ServerEnvironmentImpl;
+
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Singleton;
+import org.jvnet.hk2.config.types.Property;
+
+/**
+ * Utility file to copy the security related config files
+ * from the passed non-embedded instanceDir to the embedded
+ * server instance's config.
+ * This is a service that is protected. This implements
+ * the Contract EmbeddedSecurity
+ *
+ * @author Nithya Subramanian
+ */
+
+@Service
+@Singleton
+public class EmbeddedSecurityUtil implements EmbeddedSecurity {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ public void copyConfigFiles(ServiceLocator habitat, File fromInstanceDir, File domainXml) {
+ //For security reasons, permit only an embedded server instance to carry out the copy operations
+ ServerEnvironment se = habitat.getService(ServerEnvironment.class);
+ if (!isEmbedded(se)) {
+ return;
+ }
+
+ if ((fromInstanceDir == null) || (domainXml == null)) {
+ throw new IllegalArgumentException("Null inputs");
+ }
+
+ File toInstanceDir = habitat.<ServerEnvironmentImpl>getService(ServerEnvironmentImpl.class).getInstanceRoot();
+
+ List<String> fileNames = new ArrayList<String>();
+
+ //Handling the exception here, since it is causing CTS failure - CR 6981191
+
+ try {
+
+ //Add FileRealm keyfiles to the list
+ fileNames.addAll(new EmbeddedSecurityUtil().new DomainXmlSecurityParser(domainXml).getAbsolutePathKeyFileNames(fromInstanceDir));
+
+ //Add keystore and truststore files
+
+ // For the embedded server case, will the system properties be set in case of multiple embedded instances?
+ //Not sure - so obtain the other files from the usual locations instead of from the System properties
+
+ String keyStoreFileName = fromInstanceDir + File.separator + "config" + File.separator + "keystore.jks";
+ String trustStoreFileName = fromInstanceDir + File.separator + "config" + File.separator + "cacerts.jks";
+
+ fileNames.add(keyStoreFileName);
+ fileNames.add(trustStoreFileName);
+
+ //Add login.conf and security policy
+
+ String loginConf = fromInstanceDir + File.separator + "config" + File.separator + "login.conf";
+ String secPolicy = fromInstanceDir + File.separator + "config" + File.separator + "server.policy";
+
+ fileNames.add(loginConf);
+ fileNames.add(secPolicy);
+
+ File toConfigDir = new File(toInstanceDir, "config");
+ if (!toConfigDir.exists()) {
+ if(!toConfigDir.mkdir()) {
+ throw new IOException();
+ }
+ }
+
+ //Copy files into new directory
+ for (String fileName : fileNames) {
+ FileUtils.copyFile(new File(fileName), new File(toConfigDir, parseFileName(fileName)));
+ }
+ }catch(IOException e) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.ioError, e);
+ }catch(XMLStreamException e) {
+ _logger.log(Level.WARNING, SecurityLoggerInfo.xmlStreamingError, e);
+ }
+
+
+
+ }
+
+ public String parseFileName(String fullFilePath) {
+ if (fullFilePath == null) {
+ return null;
+ }
+ File file = new File(fullFilePath);
+ return file.getName();
+
+ }
+
+ public boolean isEmbedded(ServerEnvironment se) {
+ if (se.getRuntimeType() == RuntimeType.EMBEDDED) {
+ return true;
+ }
+ return false;
+ }
+
+ public List<String> getKeyFileNames(SecurityService securityService) {
+ List<String> keyFileNames = new ArrayList<String>();
+
+ List<AuthRealm> authRealms = securityService.getAuthRealm();
+ for (AuthRealm authRealm : authRealms) {
+ String className = authRealm.getClassname();
+ if ("com.sun.enterprise.security.auth.realm.file.FileRealm".equals(className)) {
+ List<Property> props = authRealm.getProperty();
+ for (Property prop : props) {
+ if ("file".equals(prop.getName())) {
+ keyFileNames.add(prop.getValue());
+ }
+ }
+ }
+ }
+
+ return keyFileNames;
+ }
+
+ //Inner class to parse the domainXml to obtain the keyfile names
+ class DomainXmlSecurityParser {
+
+ XMLStreamReader xmlReader;
+ XMLInputFactory xif =
+ (XMLInputFactory.class.getClassLoader() == null)
+ ? XMLInputFactory.newInstance()
+ : XMLInputFactory.newInstance(XMLInputFactory.class.getName(),
+ XMLInputFactory.class.getClassLoader());
+
+ private static final String AUTH_REALM = "auth-realm";
+ private static final String CONFIG = "config";
+ private static final String CLASSNAME = "classname";
+ private static final String FILE_REALM_CLASS = "com.sun.enterprise.security.auth.realm.file.FileRealm";
+ private static final String PROPERTY = "property";
+ private static final String NAME = "name";
+ private static final String VALUE = "value";
+ private static final String FILE = "file";
+ private static final String INSTANCE_DIR_PLACEHOLDER = "${com.sun.aas.instanceRoot}";
+
+ DomainXmlSecurityParser(File domainXml) throws XMLStreamException, FileNotFoundException {
+ xif.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
+ xif.setProperty("javax.xml.stream.isValidating", true);
+ xmlReader = xif.createXMLStreamReader(new FileReader(domainXml));
+ }
+
+ private String replaceInstanceDir(String fromInstanceDir, String keyFileName) {
+ return StringUtils.replace(keyFileName, INSTANCE_DIR_PLACEHOLDER, fromInstanceDir);
+
+ }
+ //Obtain the keyfile names for the server-config (the first appearing config in domain.xml
+ List<String> getAbsolutePathKeyFileNames(File fromInstanceDir) throws XMLStreamException {
+ List<String> keyFileNames = new ArrayList<String>();
+ while (skipToStartButNotPast(AUTH_REALM, CONFIG)) {
+ String realmClass = xmlReader.getAttributeValue(null, CLASSNAME);
+ if (realmClass.equals(FILE_REALM_CLASS)) {
+ while (skipToStartButNotPast(PROPERTY, AUTH_REALM)) {
+ if (FILE.equals(xmlReader.getAttributeValue(null, NAME))) {
+ String keyFileName = xmlReader.getAttributeValue(null, VALUE);
+ //Replace the Placeholder in the keyfile names
+ keyFileNames.add(replaceInstanceDir(fromInstanceDir.getAbsolutePath(),keyFileName ));
+
+ }
+ }
+ }
+ }
+ return keyFileNames;
+ }
+
+ private boolean skipToStartButNotPast(String startName, String stopName) throws XMLStreamException {
+ if (!StringUtils.ok(startName) || !StringUtils.ok(stopName)) {
+ throw new IllegalArgumentException();
+ }
+
+ while (xmlReader.hasNext()) {
+ xmlReader.next();
+ // getLocalName() will throw an exception in many states. Be careful!!
+ if (xmlReader.isStartElement() && startName.equals(xmlReader.getLocalName())) {
+ return true;
+ }
+ if (xmlReader.isEndElement() && stopName.equals(xmlReader.getLocalName())) {
+ return false;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/factory/SecurityManagerFactory.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/factory/SecurityManagerFactory.java
new file mode 100644
index 0000000..5887a83
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/factory/SecurityManagerFactory.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.factory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author monzillo
+ */
+public class SecurityManagerFactory {
+
+ protected SecurityManagerFactory() {
+ //do not allow creation of this base class directly
+ }
+ /**
+ * find SecurityManager by policy context identifier and name (as
+ * secondary key). There is a separate SecurityManager for each EJB of
+ * a module; they all share the same policy context identifier, and are
+ * differentiated by (ejb) name. There is one SecurityManager per web
+ * module/policy context identifier.
+ *
+ * @param iD2sMmap maps policy context id (as key) to subordinate map
+ * (as value) of (module) name (as key) to SecurityManagers (as value).
+ * @param ctxId the policy context identifier (i.e., the primary key of the
+ * lookup
+ * @param name the name of the component (e.g., the ejb name when looking up
+ * an EJBSecurityManager. for WebSecurityManagers this value should be null
+ * @param remove boolean indicating whether the corresponding SecurityManager
+ * is to be deleted from the map.
+ * @return the selected SecurityManager or null.
+ */
+ public<T> T getManager(Map<String, Map<String, T>> iD2sMmap,
+ String ctxId, String name, boolean remove) {
+
+ T manager = null;
+
+ synchronized (iD2sMmap) {
+ Map<String, T> managerMap = iD2sMmap.get(ctxId);
+ if (managerMap != null) {
+ manager = managerMap.get(name);
+ if (remove) {
+ managerMap.remove(name);
+ if (managerMap.isEmpty()) {
+ iD2sMmap.remove(ctxId);
+ }
+ }
+ }
+
+ }
+
+ return manager;
+ }
+
+ /**
+ * Get all SecurityManagers associated with a policy context identifier.
+ * EJBs from the same jar, all share the same policy context identifier, but
+ * each have their own SecurityManager. WebSecurityManager(s)
+ * map 1-to-1 to policy context identifier.
+ *
+ * @param iD2sMmap maps policy context id (as key) to subordinate map
+ * (as value) of (module) name (as key) to SecurityManagers (as value).
+ * @param ctxId the policy context identifier (i.e., the lookup key).
+ * @param remove boolean indicating whether the corresponding
+ * SecurityManager(s) are to be deleted from the map.
+ * @return a non-empty ArrayList containing the selected managers, or null.
+ */
+ public <T> ArrayList<T> getManagers(Map<String, Map<String, T>> iD2sMmap,
+ String ctxId, boolean remove) {
+
+ ArrayList<T> managers = null;
+
+ synchronized (iD2sMmap) {
+ Map<String, T> managerMap = iD2sMmap.get(ctxId);
+
+ if (managerMap != null && !managerMap.isEmpty()) {
+ managers = new ArrayList(managerMap.values());
+ }
+ if (remove) {
+ iD2sMmap.remove(ctxId);
+ }
+ }
+ return managers;
+ }
+
+ /**
+ * Get (Web or EJB) SecurityManagers associated with an application.
+ * Note that the WebSecurityManager and EJBSecurityManager classes manage
+ * separate maps for their respectibe security manager types.
+ *
+ * @param iD2sMmap maps policy context id (as key) to subordinate map
+ * (as value) of (module) name (as key) to SecurityManagers (as value).
+ * @param app2iDmap maps appName (as key) to list of policy context
+ * identifiers (as value).
+ * @param appName the application name, (i.e., the lookup key)
+ * @param remove boolean indicating whether the corresponding mappings
+ * are to be removed from the app2iDmap and aiD2sMmap.
+ * @return a non-empty ArrayList containing the selected managers, or null.
+ */
+ public <T> ArrayList<T> getManagersForApp(Map<String, Map<String, T>> iD2sMmap,
+ Map<String, ArrayList<String>> app2iDmap, String appName, boolean remove) {
+
+ ArrayList<T> managerList = null;
+ String[] ctxIds = getContextsForApp(app2iDmap, appName, remove);
+ if (ctxIds != null) {
+ ArrayList<T> managers = null;
+ synchronized (iD2sMmap) {
+ for (String id : ctxIds) {
+ managers = getManagers(iD2sMmap, id, remove);
+ if (managers != null) {
+ if (managerList == null) {
+ managerList = new ArrayList<T>();
+ }
+ managerList.addAll(managers);
+ }
+ }
+ }
+ }
+
+ return managerList;
+ }
+
+ /**
+ * Get (EJB or Web) Policy context identifiers for app.
+ *
+ * @param app2iDmap maps appName (as key) to list of policy context
+ * identifiers (as value).
+ * @param appName the application name, (i.e., the lookup key).
+ * @param remove boolean indicating whether the corresponding mappings
+ * are to be removed from the app2iDmap.
+ * @return a non-zero length array containing the selected
+ * policy context identifiers, or null.
+ */
+ public <T> String[] getContextsForApp(Map<String, ArrayList<String>> app2iDmap,
+ String appName, boolean remove) {
+
+ String[] ctxIds = null;
+
+ synchronized (app2iDmap) {
+
+ ArrayList<String> ctxList = app2iDmap.get(appName);
+ if (ctxList != null && !ctxList.isEmpty()) {
+ ctxIds = ctxList.toArray(new String[ctxList.size()]);
+ }
+ if (remove) {
+ app2iDmap.remove(appName);
+ }
+ }
+
+ return ctxIds;
+ }
+
+ /**
+ * In iD2sMmap, maps manager to ctxId and name, and in app2iDmap,
+ * includes ctxID in values mapped to appName.
+ *
+ * @param iD2sMmap maps policy context id (as key) to subordinate map
+ * (as value) of (module) name (as key) to SecurityManagers (as value).
+ * @param app2iDmap maps appName (as key) to list of policy context
+ * identifiers (as value).
+ * @param ctxId the policy context identifier
+ * @param name the component name (the EJB name or null for web modules)
+ * @param appName the application name
+ * @param manager the SecurityManager
+ */
+ public <T> void addManagerToApp(Map<String, Map<String, T>> iD2sMmap,
+ Map<String, ArrayList<String>> app2iDmap,
+ String ctxId, String name, String appName, T manager) {
+
+ synchronized (iD2sMmap) {
+
+ Map<String, T> managerMap = iD2sMmap.get(ctxId);
+
+ if (managerMap == null) {
+ managerMap = new HashMap<String, T>();
+ iD2sMmap.put(ctxId, managerMap);
+ }
+
+ managerMap.put(name, manager);
+ }
+ synchronized (app2iDmap) {
+ ArrayList<String> ctxList = app2iDmap.get(appName);
+
+ if (ctxList == null) {
+ ctxList = new ArrayList<String>();
+ app2iDmap.put(appName, ctxList);
+ }
+
+ if (!ctxList.contains(ctxId)) {
+ ctxList.add(ctxId);
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/jauth/callback/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jauth/callback/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jauth/callback/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/callback/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/callback/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/callback/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/config/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/config/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/jmac/config/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/provider/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/provider/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/provider/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLImpl.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLImpl.java
new file mode 100644
index 0000000..75a5f38
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLImpl.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import java.net.Socket;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSocket;
+import org.glassfish.grizzly.config.ssl.SSLImplementation;
+import org.glassfish.grizzly.config.ssl.ServerSocketFactory;
+import org.glassfish.grizzly.ssl.SSLSupport;
+import org.jvnet.hk2.annotations.ContractsProvided;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ *
+ * @author Sudarsan Sridhar
+ */
+@Service(name="com.sun.enterprise.security.ssl.GlassfishSSLImpl")
+@ContractsProvided({GlassfishSSLImpl.class, SSLImplementation.class})
+public class GlassfishSSLImpl extends SSLImplementation {
+ public GlassfishSSLImpl() {
+ }
+
+ public String getImplementationName() {
+ return "Glassfish";
+ }
+
+ public ServerSocketFactory getServerSocketFactory() {
+ return new GlassfishServerSocketFactory();
+ }
+
+ public SSLSupport getSSLSupport(Socket socket) {
+ if(socket instanceof SSLSocket) {
+ return new GlassfishSSLSupport((SSLSocket)socket);
+ }
+ return null;
+ }
+
+ public SSLSupport getSSLSupport(SSLEngine ssle) {
+ return new GlassfishSSLSupport(ssle);
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java
new file mode 100644
index 0000000..535ae0d
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import org.glassfish.grizzly.ssl.SSLSupport;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.cert.CertificateFactory;
+import java.util.logging.Level;
+import javax.security.cert.X509Certificate;
+import java.util.logging.Logger;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
+/**
+ *
+ * @author Sudarsan Sridhar
+ */
+public class GlassfishSSLSupport implements SSLSupport {
+
+ private final static Logger logger = SecurityLoggerInfo.getLogger();
+
+ /**
+ * A mapping table to determine the number of effective bits in the key
+ * when using a cipher suite containing the specified cipher name. The
+ * underlying data came from the TLS Specification (RFC 2246), Appendix C.
+ */
+ private static final CipherData ciphers[] = {
+ new CipherData("_WITH_NULL_", 0),
+ new CipherData("_WITH_IDEA_CBC_", 128),
+ new CipherData("_WITH_RC2_CBC_40_", 40),
+ new CipherData("_WITH_RC4_40_", 40),
+ new CipherData("_WITH_RC4_128_", 128),
+ new CipherData("_WITH_DES40_CBC_", 40),
+ new CipherData("_WITH_DES_CBC_", 56),
+ new CipherData("_WITH_3DES_EDE_CBC_", 168),
+ new CipherData("_WITH_AES_128_", 128),
+ new CipherData("_WITH_AES_256_", 256)
+ };
+
+ private final SSLSocket socket;
+ private final SSLEngine engine;
+ private SSLSession session;
+
+ public GlassfishSSLSupport(SSLSocket socket) {
+ this.socket = socket;
+ this.engine = null;
+ session = socket.getSession();
+ }
+
+ public GlassfishSSLSupport(SSLEngine engine) {
+ this.socket = null;
+ this.engine = engine;
+ if(engine != null) {
+ session = engine.getSession();
+ }
+ }
+
+ public String getCipherSuite() throws IOException {
+ if (session == null) {
+ return null;
+ }
+ return session.getCipherSuite();
+ }
+
+ public Object[] getPeerCertificateChain() throws IOException {
+ return getPeerCertificateChain(false);
+ }
+
+ public Object[] getPeerCertificateChain(boolean force) throws IOException {
+ if (session == null) {
+ return null;
+ }
+ X509Certificate[] certs = null;
+ certs = session.getPeerCertificateChain();
+ if (certs == null) {
+ certs = new X509Certificate[0];
+ }
+ if (certs.length == 0 && force) {
+ session.invalidate();
+ handshake();
+
+ if (socket == null) {
+ session = engine.getSession();
+ } else {
+ session = socket.getSession();
+ }
+ }
+ return getX509Certs();
+ }
+
+ public Integer getKeySize() throws IOException {
+ if (session == null) {
+ return null;
+ }
+ Integer keySize = (Integer) session.getValue(KEY_SIZE_KEY);
+ if (keySize == null) {
+ int size = 0;
+ String cipherSuite = session.getCipherSuite();
+ for (CipherData cipher : ciphers) {
+ if (cipherSuite.contains(cipher.phrase)) {
+ size = cipher.keySize;
+ break;
+ }
+ }
+ keySize = size;
+ session.putValue(KEY_SIZE_KEY, keySize);
+ }
+ return keySize;
+ }
+
+ public String getSessionId() throws IOException {
+ if (session == null) {
+ return null;
+ }
+ byte[] sessionId = session.getId();
+ if (sessionId == null) {
+ return null;
+ }
+ StringBuilder Id = new StringBuilder();
+ for (byte b : sessionId) {
+ String digit = Integer.toHexString(b);
+ if (digit.length() < 2) {
+ Id.append('0');
+ } else if (digit.length() > 2) {
+ digit = digit.substring(digit.length() - 2);
+ }
+ Id.append(digit);
+ }
+ return Id.toString();
+ }
+
+ private void handshake() throws IOException {
+ socket.setNeedClientAuth(true);
+ socket.startHandshake();
+ }
+
+ private Object[] getX509Certs() {
+ X509Certificate certs[] = null;
+ try {
+ certs = session.getPeerCertificateChain();
+ } catch (Throwable ex) {
+ // Get rid of the warning in the logs when no Client-Cert is
+ // available
+ }
+
+ if (certs == null) {
+ certs = new X509Certificate[0];
+ }
+ java.security.cert.X509Certificate[] x509Certs =
+ new java.security.cert.X509Certificate[certs.length];
+ for (int i = 0; i < x509Certs.length; i++) {
+ try {
+ byte buffer[] = certs[i].getEncoded();
+ CertificateFactory cf =
+ CertificateFactory.getInstance("X.509");
+ ByteArrayInputStream stream =
+ new ByteArrayInputStream(buffer);
+ x509Certs[i] = (java.security.cert.X509Certificate) cf.generateCertificate(stream);
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.log(Level.FINE, "Cert #{0} = {1}", new Object[]{i, x509Certs[i]});
+ }
+ } catch (Exception ex) {
+ logger.log(Level.INFO, SecurityLoggerInfo.convertingCertError, new Object[] {certs[i], ex.toString()});
+ return null;
+ }
+ }
+
+ if (x509Certs.length < 1) {
+ return null;
+ }
+ return x509Certs;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishServerSocketFactory.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishServerSocketFactory.java
new file mode 100644
index 0000000..c2e2d76
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishServerSocketFactory.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.util.logging.Level;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.X509KeyManager;
+
+import org.glassfish.grizzly.config.ssl.JSSE14SocketFactory;
+import org.glassfish.internal.api.Globals;
+
+/**
+ *
+ * @author Sudarsan Sridhar
+ */
+public class GlassfishServerSocketFactory extends JSSE14SocketFactory {
+
+ private SSLUtils sslUtils;
+
+ @Override
+ protected KeyManager[] getKeyManagers(String algorithm, String keyAlias) throws Exception {
+ if (sslUtils == null) {
+ initSSLUtils();
+ }
+ String keystoreFile = (String) attributes.get("keystore");
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE, "Keystore file= {0}", keystoreFile);
+ }
+
+ String keystoreType = (String) attributes.get("keystoreType");
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE, "Keystore type= {0}", keystoreType);
+ }
+ KeyManager[] kMgrs = sslUtils.getKeyManagers(algorithm);
+ if (keyAlias != null && keyAlias.length() > 0 && kMgrs != null) {
+ for (int i = 0; i < kMgrs.length; i++) {
+ kMgrs[i] = new J2EEKeyManager((X509KeyManager) kMgrs[i], keyAlias);
+ }
+ }
+ return kMgrs;
+ }
+
+ @Override
+ protected KeyStore getTrustStore() throws IOException {
+ if (sslUtils == null) {
+ initSSLUtils();
+ }
+ return sslUtils.getTrustStore();
+ }
+
+ private void initSSLUtils() {
+ if (sslUtils == null) {
+ if (Globals.getDefaultHabitat() != null) {
+ sslUtils = Globals.getDefaultHabitat().getService(SSLUtils.class);
+ } else {
+ sslUtils = new SSLUtils();
+ sslUtils.postConstruct();
+ }
+ }
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java
new file mode 100644
index 0000000..9450129
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509KeyManager;
+import javax.security.auth.Subject;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+//import com.sun.enterprise.Switch;
+import com.sun.enterprise.security.common.ClientSecurityContext;
+import com.sun.enterprise.security.auth.login.common.X509CertificateCredential;
+//copied code from LoginContextDriver to break dependency
+//import com.sun.enterprise.security.auth.login.common.LoginContextDriver;
+import com.sun.enterprise.security.auth.login.common.LoginException;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import com.sun.enterprise.security.common.AppservAccessController;
+import com.sun.enterprise.security.common.SecurityConstants;
+import com.sun.enterprise.security.common.Util;
+
+import java.util.logging.*;
+import com.sun.logging.*;
+import java.security.PrivilegedAction;
+import java.util.Set;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.security.auth.login.LoginContext;
+import com.sun.enterprise.security.ssl.manager.UnifiedX509KeyManager;
+
+/**
+ * This a J2EE specific Key Manager class that is used to select
+ * user certificates for SSL client authentication. It delegates most
+ * of the functionality to the provider specific KeyManager class.
+ * @author Vivek Nagar
+ * @author Harpreet Singh
+ */
+public final class J2EEKeyManager /*implements X509KeyManager */ extends X509ExtendedKeyManager {
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ private X509KeyManager mgr = null; // delegate
+
+ private String alias = null;
+
+ private Map<String, X509KeyManager> tokenName2MgrMap = null;
+ private boolean supportTokenAlias = false;
+
+ public J2EEKeyManager(X509KeyManager mgr, String alias) {
+ this.mgr = mgr;
+ this.alias = alias;
+
+ if (mgr instanceof UnifiedX509KeyManager) {
+ UnifiedX509KeyManager umgr = (UnifiedX509KeyManager)mgr;
+ X509KeyManager[] mgrs = umgr.getX509KeyManagers();
+ String[] tokenNames = umgr.getTokenNames();
+
+ tokenName2MgrMap = new HashMap<String, X509KeyManager>();
+ for (int i = 0; i < mgrs.length; i++) {
+ if (tokenNames[i] != null) {
+ tokenName2MgrMap.put(tokenNames[i], mgrs[i]);
+ }
+ }
+ supportTokenAlias = (tokenName2MgrMap.size() > 0);
+ }
+ }
+
+ public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
+ return mgr.chooseClientAlias(keyType, issuers, null);
+ }
+
+ public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
+ return alias;
+ }
+
+ /**
+ * Choose the client alias that will be used to select the client
+ * certificate for SSL client auth.
+ * @param the keytype
+ * @param the certificate issuers.
+ * @param the socket used for this connection. This parameter can be null,
+ * in which case the method will return the most generic alias to use.
+ * @return the alias.
+ */
+ public String chooseClientAlias(String[] keyType, Principal[] issuers,
+ Socket socket) {
+
+ String clientAlias = null;
+
+ if(this.alias == null){
+ //InvocationManager im = Switch.getSwitch().getInvocationManager();
+ //if (im == null) {
+ if(Util.getInstance().isNotServerOrACC()) {
+ // standalone client
+ clientAlias = mgr.chooseClientAlias(keyType, issuers, socket);
+ } else {
+ //ComponentInvocation ci = im.getCurrentInvocation();
+ //if (ci == null) { // 4646060
+ // throw new InvocationException();
+ //}
+ //Object containerContext = ci.getContainerContext();
+ //if(containerContext != null &&
+ //(containerContext instanceof AppContainer)) {
+ if (Util.getInstance().isACC()) {
+ ClientSecurityContext ctx = ClientSecurityContext.getCurrent();
+ Subject s = ctx.getSubject();
+ if (s == null) {
+ // pass the handler and do the login
+ //TODO V3: LoginContextDriver.doClientLogin(AppContainer.CERTIFICATE,
+ //AppContainer.getCallbackHandler());
+ doClientLogin(SecurityConstants.CERTIFICATE,
+ Util.getInstance().getCallbackHandler());
+ s = ctx.getSubject();
+ }
+ Iterator itr = s.getPrivateCredentials().iterator();
+ while(itr.hasNext()) {
+ Object o = itr.next();
+ if(o instanceof X509CertificateCredential) {
+ X509CertificateCredential crt =
+ (X509CertificateCredential) o;
+ clientAlias = crt.getAlias();
+ break;
+ }
+ }
+ }
+ }
+ }else{
+ clientAlias = this.alias;
+ }
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "Choose client Alias :{0}", clientAlias);
+ }
+ return clientAlias;
+ }
+
+ /**
+ * Choose the server alias that will be used to select the server
+ * certificate for SSL server auth.
+ * @param the keytype
+ * @param the certificate issuers.
+ * @param the socket used for this connection. This parameter can be null,
+ * in which case the method will return the most generic alias to use.
+ * @return the alias
+ */
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket) {
+
+ String serverAlias = null;
+ if(this.alias != null){
+ serverAlias = this.alias;
+ }else{
+ serverAlias = mgr.chooseServerAlias(keyType, issuers, socket);
+ }
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "Choosing server alias :{0}", serverAlias);
+ }
+ return serverAlias;
+ }
+
+ /**
+ * Return the certificate chain for the specified alias.
+ * @param the alias.
+ * @return the chain of X509 Certificates.
+ */
+ public X509Certificate[] getCertificateChain(String alias) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Getting certificate chain");
+ }
+ X509KeyManager keyMgr = getManagerFromToken(alias);
+ if (keyMgr != null) {
+ String aliasName = alias.substring(alias.indexOf(':') + 1);
+ return keyMgr.getCertificateChain(aliasName);
+ } else {
+ return mgr.getCertificateChain(alias);
+ }
+ }
+
+ /**
+ * Return all the available client aliases for the specified key type.
+ * @param the keytype
+ * @param the certificate issuers.
+ * @return the array of aliases.
+ */
+ public String[] getClientAliases(String keyType, Principal[] issuers) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Getting client aliases");
+ }
+ return mgr.getClientAliases(keyType, issuers);
+ }
+
+ /**
+ * Return all the available server aliases for the specified key type.
+ * @param the keytype
+ * @param the certificate issuers.
+ * @return the array of aliases.
+ */
+ public String[] getServerAliases(String keyType, Principal[] issuers) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE,"Getting server aliases");
+ }
+ return mgr.getServerAliases(keyType, issuers);
+ }
+
+ /**
+ * Return the private key for the specified alias.
+ * @param the alias.
+ * @return the private key.
+ */
+ public PrivateKey getPrivateKey(String alias) {
+ if(_logger.isLoggable(Level.FINE)){
+ _logger.log(Level.FINE, "Getting private key for alias:{0}", alias);
+ }
+ X509KeyManager keyMgr = getManagerFromToken(alias);
+ if (keyMgr != null) {
+ String aliasName = alias.substring(alias.indexOf(':') + 1);
+ return keyMgr.getPrivateKey(aliasName);
+ } else {
+ return mgr.getPrivateKey(alias);
+ }
+ }
+
+
+ /**
+ * Find the corresponding X509KeyManager associated to token in alias.
+ * It returns null if there is n
+ * @param tokenAlias of the form <tokenName>:<aliasName>
+ */
+ private X509KeyManager getManagerFromToken(String tokenAlias) {
+ X509KeyManager keyMgr = null;
+ int ind = -1;
+ if (supportTokenAlias && tokenAlias != null && (ind = tokenAlias.indexOf(':')) != -1) {
+ String tokenName = alias.substring(0, ind);
+ keyMgr = tokenName2MgrMap.get(tokenName);
+ }
+ return keyMgr;
+ }
+
+ //TODO:V3 copied all method(s)below from LoginContextDriver to break dependencies among modules
+ private static final String CLIENT_JAAS_PASSWORD = "default";
+ /**
+ * Perform login on the client side.
+ * It just simulates the login on the client side.
+ * The method uses the callback handlers and generates correct
+ * credential information that will be later sent to the server
+ * @param int type whether it is <i> username_password</i> or
+ * <i> certificate </i> based login.
+ * @param CallbackHandler the callback handler to gather user information.
+ * @exception LoginException the exception thrown by the callback handler.
+ */
+ public static Subject doClientLogin(int type,
+ javax.security.auth.callback.CallbackHandler jaasHandler)
+ throws LoginException
+ {
+ final javax.security.auth.callback.CallbackHandler handler =
+ jaasHandler;
+ // the subject will actually be filled in with a PasswordCredential
+ // required by the csiv2 layer in the LoginModule.
+ // we create the dummy credential here and call the
+ // set security context. Thus, we have 2 credentials, one each for
+ // the csiv2 layer and the other for the RI.
+ final Subject subject = new Subject();
+ //V3:Commented : TODO uncomment later for Appcontainer
+ if (type == SecurityConstants.USERNAME_PASSWORD){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ lg.login();
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ postClientAuth(subject, PasswordCredential.class);
+ return subject;
+ } else if (type == SecurityConstants.CERTIFICATE){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_CERTIFICATE,
+ subject, handler);
+ lg.login();
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ postClientAuth(subject, X509CertificateCredential.class);
+ return subject;
+ } else if (type == SecurityConstants.ALL){
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lgup =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ LoginContext lgc =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_CERTIFICATE,
+ subject, handler);
+ lgup.login();
+ postClientAuth(subject, PasswordCredential.class);
+
+ lgc.login();
+ postClientAuth(subject,
+ X509CertificateCredential.class);
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+
+ return null;
+ }
+ });
+ return subject;
+ } else{
+ AppservAccessController.doPrivileged(new PrivilegedAction() {
+ public java.lang.Object run() {
+ try{
+ LoginContext lg =
+ new LoginContext(SecurityConstants.CLIENT_JAAS_PASSWORD,
+ subject, handler);
+ lg.login();
+ postClientAuth(subject, PasswordCredential.class);
+ }catch(javax.security.auth.login.LoginException e){
+ throw (LoginException)
+ new LoginException(e.toString()).initCause(e);
+ }
+ return null;
+ }
+ });
+ return subject;
+ }
+ }
+
+ /**
+ * Extract the relevant username and realm information from the
+ * subject and sets the correct state in the security context. The
+ * relevant information is set into the Thread Local Storage from
+ * which then is extracted to send over the wire.
+ *
+ * @param Subject the subject returned by the JAAS login.
+ * @param Class the class of the credential object stored in the subject
+ *
+ */
+ private static void postClientAuth(Subject subject, Class<?> clazz){
+ final Class<?> clas = clazz;
+ final Subject fs = subject;
+ Set credset =
+ (Set) AppservAccessController.doPrivileged(new PrivilegedAction<Set>() {
+ public Set run() {
+ if(_logger.isLoggable(Level.FINEST)){
+ _logger.log(Level.FINEST, "LCD post login subject :{0}", fs);
+ }
+ return fs.getPrivateCredentials(clas);
+ }
+ });
+ final Iterator iter = credset.iterator();
+ while(iter.hasNext()) {
+ Object obj = null;
+ try{
+ obj = AppservAccessController.doPrivileged(new PrivilegedAction(){
+ public java.lang.Object run(){
+ return iter.next();
+ }
+ });
+ } catch (Exception e){
+ // should never come here
+ _logger.log(Level.SEVERE,
+ SecurityLoggerInfo.securityAccessControllerActionError,
+ e);
+ }
+ if(obj instanceof PasswordCredential) {
+ PasswordCredential p = (PasswordCredential) obj;
+ String user = p.getUser();
+ if(_logger.isLoggable(Level.FINEST)){
+ String realm = p.getRealm();
+ _logger.log(Level.FINEST, "In LCD user-pass login:{0} realm :{1}",
+ new Object[]{user, realm});
+ }
+ setClientSecurityContext(user, fs);
+ return;
+ } else if (obj instanceof X509CertificateCredential){
+ X509CertificateCredential p = (X509CertificateCredential) obj;
+ String user = p.getAlias();
+ if(_logger.isLoggable(Level.FINEST)){
+ String realm = p.getRealm();
+ _logger.log(Level.FINEST, "In LCD cert-login::{0} realm :{1}",
+ new Object[]{user, realm});
+ }
+ setClientSecurityContext(user, fs);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Sets the security context on the appclient side.
+ * It sets the relevant information into the TLS
+ * @param String username is the user who authenticated
+ * @param Subject is the subject representation of the user
+ * @param Credentials the credentials that the server associated with it
+ */
+ private static void setClientSecurityContext(String username,
+ Subject subject) {
+
+ ClientSecurityContext securityContext =
+ new ClientSecurityContext(username, subject);
+ ClientSecurityContext.setCurrent(securityContext);
+ }
+
+}
+
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/JarSigner.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/JarSigner.java
new file mode 100644
index 0000000..ed0aad8
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/JarSigner.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import com.sun.enterprise.server.pluggable.SecuritySupport;
+import com.sun.enterprise.universal.GFBase64Encoder;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.KeyStoreException;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import sun.security.pkcs.ContentInfo;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.X500Name;
+
+/**
+ * A utility class to sign jar files.
+ *
+ * @author Sudarsan Sridhar
+ */
+public class JarSigner {
+
+ private static final GFBase64Encoder b64encoder = new GFBase64Encoder();
+ private final MessageDigest md;
+ private final String digestAlgorithm;
+ private final String keyAlgorithm;
+ private static final SecuritySupport secSupp = SecuritySupport.getDefaultInstance();
+
+ public JarSigner(String digestAlgorithm, String keyAlgorithm)
+ throws NoSuchAlgorithmException {
+ this.digestAlgorithm = digestAlgorithm;
+ this.keyAlgorithm = keyAlgorithm;
+ this.md = MessageDigest.getInstance(digestAlgorithm);
+ }
+
+ public static void main(String[] args) throws Exception {
+ File in = new File(args[0]);
+ File out = new File(args[1]);
+ new JarSigner("SHA1", "RSA").signJar(in, out, "s1as");
+ }
+
+ /**
+ * Hash the string completely.
+ *
+ * @param content String to be hashed.
+ * @return the hash.
+ */
+ private String hash(String content) {
+ return hash(content.getBytes());
+ }
+
+ /**
+ * Hash the data.
+ *
+ * @param data
+ * @return
+ */
+ private String hash(final byte[] data) {
+ return b64encoder.encodeBuffer(md.digest(data)).trim();
+ }
+
+ /**
+ * Signs a jar.
+ *
+ * @param input input jar file
+ * @param output output jar file
+ * @param alias signing alias in the keystore
+ */
+ public void signJar(File input, File output, String alias)
+ throws IOException, KeyStoreException, NoSuchAlgorithmException,
+ InvalidKeyException, UnrecoverableKeyException, SignatureException {
+
+ signJar(input, output, alias, null);
+ }
+
+ /**
+ * Signs a JAR, adding caller-specified attributes to the manifest's main attrs.
+ *
+ * @param input input JAR file
+ * @param output output JAR file
+ * @param alias signing alias in the keystore
+ * @param additionalAttrs additional attributes to add to the manifest's main attrs (null if none)
+ */
+ public void signJar(File input, File output, String alias, final Attributes additionalAttrs)
+ throws IOException, KeyStoreException, NoSuchAlgorithmException,
+ InvalidKeyException, UnrecoverableKeyException, SignatureException {
+ final ZipOutputStream zout = new ZipOutputStream(
+ new FileOutputStream(output));
+ try {
+ signJar(input, zout, alias, additionalAttrs, Collections.EMPTY_MAP);
+ } finally {
+ zout.close();
+ }
+ }
+
+ /**
+ * Signs a JAR, adding caller-specified attributes to the manifest's main attrs and also
+ * inserting (and signing) additional caller-supplied content as new entries in the
+ * zip output stream.
+ * @param input input JAR file
+ * @param zout Zip output stream created
+ * @param alias signing alias in the keystore
+ * @param additionalAttrs additional attributes to add to the manifest's main attrs (null if none)
+ * @param additionalEntries entry-name/byte[] pairs of additional content to add to the signed output
+ * @throws IOException
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ * @throws UnrecoverableKeyException
+ * @throws SignatureException
+ */
+ public void signJar(File input, ZipOutputStream zout, String alias, final Attributes additionalAttrs,
+ Map<String,byte[]> additionalEntries)
+ throws IOException, KeyStoreException, NoSuchAlgorithmException,
+ InvalidKeyException, UnrecoverableKeyException, SignatureException {
+
+ JarFile jf = new JarFile(input);
+ try {
+ Enumeration<JarEntry> jes;
+ // manifestEntries is content of META-INF/MANIFEST.MF
+ StringBuilder manifestEntries = new StringBuilder();
+
+ byte[] manifestContent;
+ byte[] sigFileContent = getExistingSignatureFile(jf);
+ boolean signed = (sigFileContent != null);
+
+ if (!signed || ! additionalEntries.isEmpty()) {
+ jes = jf.entries();// manifestHeader is header of META-INF/MANIFEST.MF, initialized to default
+ Manifest manifest = retrieveManifest(jf);
+ StringBuilder manifestHeader = new StringBuilder();
+ Attributes mfAttrs = manifest.getMainAttributes();
+ if (additionalAttrs != null) {
+ mfAttrs.putAll(additionalAttrs);
+ }
+ appendAttributes(manifestHeader, mfAttrs);
+
+ // sigFileEntries is content of META-INF/ME.SF
+ StringBuilder sigFileEntries = new StringBuilder();
+ while (jes.hasMoreElements()) {
+ JarEntry je = jes.nextElement();
+ String name = je.getName();
+ if ((je.isDirectory() && manifest.getAttributes(name) == null)
+ || name.equals(JarFile.MANIFEST_NAME)) {
+ continue;
+ }
+ processMetadataForEntry(manifest, manifestEntries, sigFileEntries, name, readJarEntry(jf, je));
+ }
+
+ if (additionalEntries != null) {
+ for (Map.Entry<String,byte[]> entry : additionalEntries.entrySet()) {
+ processMetadataForEntry(manifest, manifestEntries, sigFileEntries, entry.getKey(), entry.getValue());
+ }
+ }
+
+ // META-INF/ME.SF
+ StringBuilder sigFile = new StringBuilder("Signature-Version: 1.0\r\n").append(digestAlgorithm).append("-Digest-Manifest-Main-Attributes: ").append(hash(manifestHeader.toString())).append("\r\n").append("Created-By: ").append(System.getProperty("java.version")).append(" (").append(System.getProperty("java.vendor")).append(")\r\n");
+ // Combine header and content of MANIFEST.MF, and rehash
+ manifestHeader.append(manifestEntries);
+ sigFile.append(digestAlgorithm).append("-Digest-Manifest: ").append(hash(manifestHeader.toString())).append("\r\n\r\n");
+
+ // Combine header and content of ME.SF
+ sigFile.append(sigFileEntries);
+ manifestContent = manifestHeader.toString().getBytes();
+ sigFileContent = sigFile.toString().getBytes();
+ } else {
+ manifestContent = readJarEntry(jf,
+ jf.getJarEntry(JarFile.MANIFEST_NAME));
+ }
+ X509Certificate[] certChain = null;
+ PrivateKey privKey = null;
+ KeyStore[] ks = secSupp.getKeyStores();
+ for (int i = 0; i < ks.length; i++) {
+ privKey = secSupp.getPrivateKeyForAlias(alias, i);
+ if (privKey != null) {
+ Certificate[] cs = ks[i].getCertificateChain(alias);
+ certChain = new X509Certificate[cs.length];
+ for (int j = 0; j < cs.length; j++) {
+ certChain[j] = (X509Certificate) cs[j];
+ }
+ }
+ }
+
+ // Sign ME.SF
+ Signature sig = Signature.getInstance(digestAlgorithm + "with" + keyAlgorithm);
+ sig.initSign(privKey);
+ sig.update(sigFileContent);
+
+ // Create PKCS7 block
+ PKCS7 pkcs7 = new PKCS7(
+ new AlgorithmId[]{AlgorithmId.get(digestAlgorithm)},
+ new ContentInfo(sigFileContent),
+ certChain,
+ new SignerInfo[]{new SignerInfo(
+ (X500Name) certChain[0].getIssuerDN(),
+ certChain[0].getSerialNumber(),
+ AlgorithmId.get(digestAlgorithm),
+ AlgorithmId.get(keyAlgorithm),
+ sig.sign())
+ });
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ pkcs7.encodeSignedData(bout);
+
+ // Write output
+
+ zout.putNextEntry((signed)
+ ? getZipEntry(jf.getJarEntry(JarFile.MANIFEST_NAME))
+ : new ZipEntry(JarFile.MANIFEST_NAME));
+ zout.write(manifestContent);
+
+ zout.putNextEntry(new ZipEntry("META-INF/"
+ + alias.toUpperCase(Locale.US) + ".SF"));
+ zout.write(sigFileContent);
+
+ zout.putNextEntry(new ZipEntry("META-INF/"
+ + alias.toUpperCase(Locale.US) + "." + keyAlgorithm));
+ zout.write(bout.toByteArray());
+
+ jes = jf.entries();
+ while (jes.hasMoreElements()) {
+ JarEntry je = jes.nextElement();
+ String name = je.getName();
+ if (!name.equals(JarFile.MANIFEST_NAME)) {
+ zout.putNextEntry(getZipEntry(je));
+ byte[] data = readJarEntry(jf, je);
+ zout.write(data);
+ }
+ }
+ if (additionalEntries != null) {
+ for (Map.Entry<String, byte[]> entry : additionalEntries.entrySet()) {
+ final ZipEntry newZipEntry = new ZipEntry(entry.getKey());
+ zout.putNextEntry(newZipEntry);
+ zout.write(entry.getValue());
+ }
+ }
+
+ } finally {
+ jf.close();
+ }
+ }
+
+ private void processMetadataForEntry(final Manifest manifest,
+ final StringBuilder manifestEntries,
+ final StringBuilder sigFileEntries,
+ final String name,
+ final byte[] content) {
+ StringBuilder me = new StringBuilder();
+ StringBuilder currentLine = new StringBuilder();
+ // Create digest lines in MANIFEST.MF
+ currentLine.append("Name: ").append(name);
+ appendLine(me, currentLine);
+ currentLine.setLength(0);
+ me.append(digestAlgorithm).append("-Digest: ").append(hash(content)).append("\r\n");
+ appendAttributes(me, manifest, name);
+ // Create digest lines in ME.SF
+ currentLine.append("Name: ").append(name);
+ appendLine(sigFileEntries, currentLine);
+ currentLine.setLength(0);
+ sigFileEntries.append(digestAlgorithm).append("-Digest: ").append(hash(me.toString())).append("\r\n\r\n");
+ manifestEntries.append(me);
+ }
+
+ /**
+ * Retrieve manifest from jar, create a default template if none exists.
+ *
+ * @param jf The jar file
+ * @return The Manifest
+ * @throws IOException
+ */
+ private Manifest retrieveManifest(JarFile jf) throws IOException {
+ Manifest manifest = jf.getManifest();
+ if (manifest == null) {
+ manifest = new Manifest();
+ Attributes mainAttributes = manifest.getMainAttributes();
+ mainAttributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
+ mainAttributes.putValue("Created-By", System.getProperty("java.version")
+ + " (" + System.getProperty("java.vendor") + ")");
+ }
+ Map<String, Attributes> entriesMap = manifest.getEntries();
+ for (Iterator<String> entries = entriesMap.keySet().iterator(); entries.hasNext();) {
+ if (jf.getJarEntry(entries.next()) == null) {
+ entries.remove();
+ }
+ }
+ return manifest;
+ }
+
+ /**
+ * Add attributes for the current entry.
+ *
+ * @param manifestEntry - The StringBuilder to which the attributes are to be added.
+ * @param manifest - The Jar Manifest Entry
+ * @param entry - The named entry in the manifest. null means the Main Attribute section.
+ * @return manifestEntry with attributes added.
+ */
+ private static StringBuilder appendAttributes(StringBuilder manifestEntry,
+ Manifest manifest, String entry) {
+ return appendAttributes(manifestEntry, (entry == null)
+ ? manifest.getMainAttributes() : manifest.getAttributes(entry));
+ }
+
+ private static StringBuilder appendAttributes(StringBuilder manifestEntry,
+ Attributes attributes) {
+ StringBuilder line = new StringBuilder();
+ if (attributes != null) {
+ for (Map.Entry attr : attributes.entrySet()) {
+ line.append(attr.getKey().toString()).append(": ").append((String) attr.getValue());
+ appendLine(manifestEntry, line);
+ line.setLength(0);
+ }
+ }
+ return manifestEntry.append("\r\n");
+ }
+
+ /**
+ * Process a long manifest line and add continuation if required
+ *
+ * @param sb - The output string
+ * @param line - The line to be processed.
+ * @return sb with the line added.
+ */
+ private static StringBuilder appendLine(StringBuilder sb, StringBuilder line) {
+ int begin = 0;
+ for (int end = 70; line.length() - begin > 70; end += 69) {
+ sb.append(line.subSequence(begin, end)).append("\r\n ");
+ begin = end;
+ }
+ return sb.append(line.subSequence(begin, line.length())).append("\r\n");
+ }
+
+ /**
+ * If jar is signed, return existing Signature file, else return null.
+ *
+ * @param jf The jar file
+ * @return Signature file
+ * @throws IOException
+ */
+ private static byte[] getExistingSignatureFile(JarFile jf) throws IOException {
+ Enumeration<JarEntry> entries = jf.entries();
+ JarEntry je = null;
+ while (entries.hasMoreElements()) {
+ JarEntry cje = entries.nextElement();
+ if (cje.getName().startsWith("META-INF/") && cje.getName().endsWith(".SF")) {
+ je = cje;
+ break;
+ }
+ }
+ return readJarEntry(jf, je);
+ }
+
+ /**
+ * Read completely the bytes from Entry je of jarfile jf.
+ *
+ * @param jf the jar file
+ * @param je the jar entry
+ * @return bytes from je.
+ * @throws IOException
+ */
+ private static byte[] readJarEntry(JarFile jf, JarEntry je) throws IOException {
+ if (je == null) {
+ return null;
+ }
+ byte[] data = new byte[(int) je.getSize()];
+ InputStream jis = jf.getInputStream(je);
+ int current;
+ int idx = 0;
+ while ((current = jis.read()) > -1) {
+ data[idx++] = (byte) current;
+ }
+ return data;
+ }
+
+ /**
+ * Get the ZipEntry for the given JarEntry. Added in order to suppress the
+ * compressedSize field as it was causing errors
+ *
+ * @param je The jar entry.
+ * @return ZipEntry with fields populated from the JarEntry.
+ */
+ private static ZipEntry getZipEntry(JarEntry je) {
+ ZipEntry ze = new ZipEntry(je.getName());
+
+ ze.setComment(je.getComment());
+ ze.setCrc(je.getCrc());
+ ze.setExtra(je.getExtra());
+ ze.setMethod(je.getMethod());
+ ze.setSize(je.getSize());
+ ze.setTime(je.getTime());
+
+ return ze;
+ }
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java
new file mode 100644
index 0000000..c3c71d8
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl;
+
+import com.sun.enterprise.security.SecurityLoggerInfo;
+import com.sun.enterprise.security.common.Util;
+import java.io.IOException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Enumeration;
+import java.security.cert.Certificate;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509KeyManager;
+
+
+//V3:Commented import com.sun.enterprise.config.clientbeans.Ssl
+import com.sun.enterprise.server.pluggable.SecuritySupport;
+//V3:Commented import com.sun.web.security.SSLSocketFactory;
+import com.sun.enterprise.security.integration.AppClientSSL;
+import java.util.logging.*;
+import com.sun.logging.*;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.Permission;
+import java.util.PropertyPermission;
+import javax.net.ssl.SSLSocketFactory;
+import org.jvnet.hk2.annotations.Service;
+import javax.inject.Inject;
+import org.glassfish.hk2.api.PostConstruct;
+
+import javax.inject.Singleton;
+
+/**
+ * Handy class containing static functions.
+ * @author Harpreet Singh
+ * @author Vivek Nagar
+ * @author Shing Wai Chan
+ */
+@Service
+@Singleton
+public final class SSLUtils implements PostConstruct {
+ private static final String DEFAULT_OUTBOUND_KEY_ALIAS = "s1as";
+ public static final String HTTPS_OUTBOUND_KEY_ALIAS = "com.sun.enterprise.security.httpsOutboundKeyAlias";
+ private static final String DEFAULT_SSL_PROTOCOL = "TLS";
+
+ private static final Logger _logger = SecurityLoggerInfo.getLogger();
+
+ @Inject
+ private SecuritySupport secSupp;
+
+ private boolean hasKey = false;
+ private KeyStore mergedTrustStore = null;
+ private AppClientSSL appclientSsl = null;
+ private SSLContext ctx = null;
+
+ public void postConstruct() {
+ try {
+ //TODO: To check the right implementation once we support EE.
+ if(secSupp == null){
+ secSupp = SecuritySupport.getDefaultInstance();
+ }
+ KeyStore[] keyStores = getKeyStores();
+ if (keyStores != null) {
+ for (KeyStore keyStore : keyStores) {
+ Enumeration aliases = keyStore.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = (String) aliases.nextElement();
+ if (keyStore.isKeyEntry(alias)) {
+ hasKey = true;
+ break;
+ }
+ }
+ if (hasKey) {
+ break;
+ }
+ }
+ }
+ mergedTrustStore = mergingTrustStores(secSupp.getTrustStores());
+ getSSLContext(null, null, null);
+ } catch(Exception ex) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "SSLUtils static init fails.", ex);
+ }
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ SSLContext getSSLContext(String protocol, String algorithm, String trustAlgorithm) {
+ try {
+ //V3:Commented to break dependency on WebTier.
+ //The SSLSocketFactory CTOR will now take care of setting the kmgr and tmgr
+ //SSLSocketFactory.setManagers(getKeyManagers(), getTrustManagers());
+
+ // Creating a default SSLContext and HttpsURLConnection for clients
+ // that use Https
+ if (protocol == null) {
+ protocol = DEFAULT_SSL_PROTOCOL;
+ }
+ ctx = SSLContext.getInstance(protocol);
+ String keyAlias = System.getProperty(HTTPS_OUTBOUND_KEY_ALIAS);
+ KeyManager[] kMgrs = getKeyManagers(algorithm);
+ if (keyAlias != null && keyAlias.length() > 0 && kMgrs != null) {
+ for (int i = 0; i < kMgrs.length; i++) {
+ kMgrs[i] = new J2EEKeyManager((X509KeyManager)kMgrs[i], keyAlias);
+ }
+ }
+ ctx.init(kMgrs, getTrustManagers(trustAlgorithm), null);
+
+ HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
+ //refer issue :http://java.net/jira/browse/GLASSFISH-15369
+ SSLContext.setDefault(ctx);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ return ctx;
+ }
+
+ public boolean verifyMasterPassword(final char[] masterPass) {
+ return secSupp.verifyMasterPassword(masterPass);
+ }
+
+ public KeyStore[] getKeyStores() throws IOException{
+ return secSupp.getKeyStores();
+ }
+
+ public KeyStore getKeyStore() throws IOException{
+ return getKeyStores()[0];
+ }
+
+ public KeyStore[] getTrustStores() throws IOException{
+ return secSupp.getTrustStores();
+ }
+
+ public KeyStore getTrustStore() throws IOException{
+ return getTrustStores()[0];
+ }
+
+ /**
+ * This API is for temporary purpose. It will be removed once JSR 196
+ * is updated.
+ */
+ public KeyStore getMergedTrustStore() {
+ return mergedTrustStore;
+ }
+
+ public KeyManager[] getKeyManagers() throws Exception{
+ return getKeyManagers(null);
+ }
+ public KeyManager[] getKeyManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException{
+ return secSupp.getKeyManagers(algorithm);
+ }
+ public TrustManager[] getTrustManagers() throws Exception{
+ return getTrustManagers(null);
+ }
+ public TrustManager[] getTrustManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException{
+ return secSupp.getTrustManagers(algorithm);
+ }
+
+
+ public void setAppclientSsl(AppClientSSL ssl){
+ appclientSsl = ssl;
+ }
+
+ public AppClientSSL getAppclientSsl() {
+ return appclientSsl;
+ }
+
+ public static String getKeyStoreType() {
+ return System.getProperty(SecuritySupport.KEYSTORE_TYPE_PROP, KeyStore.getDefaultType());
+ }
+
+ public static String getTrustStoreType() {
+ return System.getProperty(SecuritySupport.TRUSTSTORE_TYPE_PROP, KeyStore.getDefaultType());
+ }
+
+ /**
+ * This method checks whether a private key is available or not.
+ */
+ public boolean isKeyAvailable() {
+ return hasKey;
+ }
+
+ /**
+ * Check whether given String is of the form [<TokenName>:]alias
+ * where alias is an key entry.
+ * @param certNickname
+ * @return boolean
+ */
+ public boolean isTokenKeyAlias(String certNickname) throws Exception {
+ boolean isTokenKeyAlias = false;
+ if (certNickname != null) {
+ int ind = certNickname.indexOf(':');
+ KeyStore[] kstores = getKeyStores();
+ int count = -1;
+ String aliasName = null;
+ if (ind != -1) {
+ String[] tokens = secSupp.getTokenNames();
+ String tokenName = certNickname.substring(0, ind);
+ aliasName = certNickname.substring(ind + 1);
+ for (int i = 0; i < tokens.length; i++) {
+ if (tokenName.equals(tokens[i])) {
+ count = i;
+ }
+ }
+ }
+
+ if (count != -1) {
+ isTokenKeyAlias = kstores[count].isKeyEntry(aliasName);
+ } else {
+ for (KeyStore kstore : kstores) {
+ if (kstore.isKeyEntry(certNickname)) {
+ isTokenKeyAlias = true;
+ break;
+ }
+ }
+ }
+ }
+ return isTokenKeyAlias;
+ }
+
+ /**
+ * Get a PrivateKeyEntry with certNickName is of the form
+ * [<TokenName>:]alias where alias is an key entry.
+ * @param certNickname
+ * @return PrivateKeyEntry
+ */
+ public PrivateKeyEntry getPrivateKeyEntryFromTokenAlias(
+ String certNickname) throws Exception {
+ checkPermission(SecuritySupport.KEYSTORE_PASS_PROP);
+ PrivateKeyEntry privKeyEntry = null;
+ if (certNickname != null) {
+ int ind = certNickname.indexOf(':');
+ KeyStore[] kstores = getKeyStores();
+ int count = -1;
+ String aliasName = certNickname;
+ if (ind != -1) {
+ String[] tokens = secSupp.getTokenNames();
+ String tokenName = certNickname.substring(0, ind);
+ aliasName = certNickname.substring(ind + 1);
+ for (int i = 0; i < tokens.length; i++) {
+ if (tokenName.equals(tokens[i])) {
+ count = i;
+ }
+ }
+ }
+
+ if (count != -1 && kstores.length >= count) {
+ PrivateKey privKey = secSupp.getPrivateKeyForAlias(aliasName, count);
+ if (privKey != null) {
+ Certificate[] certs = kstores[count].getCertificateChain(
+ aliasName);
+ privKeyEntry = new PrivateKeyEntry(privKey, certs);
+ }
+ } else {
+ for (int i = 0; i < kstores.length; i++) {
+ PrivateKey privKey = secSupp.getPrivateKeyForAlias(aliasName, i);
+ if (privKey != null) {
+ Certificate[] certs =
+ kstores[i].getCertificateChain(
+ aliasName);
+ privKeyEntry = new PrivateKeyEntry(privKey, certs);
+ break;
+ }
+ }
+ }
+ }
+
+ return privKeyEntry;
+ }
+
+ public static void checkPermission(String key) {
+ try {
+ // Checking a random permission to check if it is server.
+ if(Util.isEmbeddedServer() || Util.getDefaultHabitat() == null
+ || Util.getInstance().isACC() || Util.getInstance().isNotServerOrACC()){
+ return;
+ }
+ Permission perm = new RuntimePermission("SSLPassword");
+ AccessController.checkPermission(perm);
+ } catch (AccessControlException e) {
+ String message = e.getMessage();
+ Permission perm = new PropertyPermission(key, "read");
+ if (message != null) {
+ message = message.replace(e.getPermission().toString(), perm.toString());
+ }
+ throw new AccessControlException(message, perm);
+ }
+ }
+
+ public String[] getSupportedCipherSuites() {
+ //postConstruct is already setting this.
+ return HttpsURLConnection.getDefaultSSLSocketFactory().getSupportedCipherSuites();
+ }
+
+ private KeyStore mergingTrustStores(KeyStore[] trustStores)
+ throws IOException, KeyStoreException,
+ NoSuchAlgorithmException, CertificateException {
+ KeyStore mergedStore;
+ try {
+ mergedStore = secSupp.loadNullStore("CaseExactJKS", secSupp.getKeyStores().length - 1);
+ } catch(KeyStoreException ex) {
+ mergedStore = secSupp.loadNullStore("JKS", secSupp.getKeyStores().length - 1);
+ }
+
+ String[] tokens = secSupp.getTokenNames();
+ for (int i = 0; i < trustStores.length; i++) {
+ Enumeration aliases = trustStores[i].aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = (String)aliases.nextElement();
+ Certificate cert = trustStores[i].getCertificate(alias);
+
+ //need to preserve the token:alias name format
+ String alias2 = (i < tokens.length - 1)? tokens[i] + ":" + alias : alias;
+
+ String alias3 = alias2;
+ boolean alreadyInStore = false;
+ Certificate aCert;
+ int count = 1;
+ while ((aCert = mergedStore.getCertificate(alias3)) != null) {
+ if (aCert.equals(cert)) {
+ alreadyInStore = true;
+ break;
+ }
+ alias3 = alias2 + "__" + count++;
+ }
+ if (!alreadyInStore) {
+ mergedStore.setCertificateEntry(alias3, cert);
+ }
+ }
+ }
+ return mergedStore;
+ }
+
+ /**
+ *
+ *
+ * @param alias the admin key alias
+ * @param protocol the protocol or null, uses "TLS" if this argument is null.
+ * @return the SSLSocketFactory from the initialized SSLContext
+ */
+ public SSLSocketFactory getAdminSocketFactory(String alias, String protocol) {
+ return getAdminSSLContext(alias, protocol).getSocketFactory();
+ }
+
+ /*
+ * @param alias the admin key alias
+ * @param protocol the protocol or null, uses "TLS" if this argument is null.
+ * @return the initialized SSLContext
+ */
+ public SSLContext getAdminSSLContext(String alias, String protocol) {
+ try {
+ if (protocol == null) {
+ protocol = "TLS";
+ }
+ SSLContext cntxt = SSLContext.getInstance(protocol);
+ KeyManager[] kMgrs = getKeyManagers();
+ if (alias != null && alias.length() > 0 && kMgrs != null) {
+ for (int i = 0; i < kMgrs.length; i++) {
+ kMgrs[i] = new J2EEKeyManager((X509KeyManager)kMgrs[i], alias);
+ }
+ }
+ cntxt.init(kMgrs, getTrustManagers(), null);
+
+ return cntxt;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/IASSecurityException.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/IASSecurityException.java
new file mode 100644
index 0000000..6e16b92
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/IASSecurityException.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.util;
+
+import java.lang.*;
+
+/**
+ * General exception class for iAS security failures.
+ *
+ * <P>This class takes advantage of the JDK1.4 Throwable objects which
+ * can carry the original cause of the exception. This prevents losing
+ * the information on what caused the problem to arise.
+ *
+ * <P>Ideally there should be common top level iAS Exceptions to extend.
+ *
+ */
+
+public class IASSecurityException extends Exception
+{
+ private boolean noMsg;
+
+ /**
+ * Constructor.
+ *
+ * @param msg The detail message.
+ *
+ */
+ public IASSecurityException(String msg)
+ {
+ super(msg);
+ noMsg=false;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param msg The detail message.
+ * @param cause The cause (which is saved for later retrieval by the
+ * getCause() method).
+ *
+ */
+ public IASSecurityException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ noMsg=false;
+ }
+
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause (which is saved for later retrieval by the
+ * getCause() method).
+ *
+ */
+ public IASSecurityException(Throwable cause)
+ {
+ super(cause);
+ noMsg=true;
+ }
+
+
+ /**
+ * Returns a description of this exception. If a root cause was included
+ * during construction, its message is also included.
+ *
+ * @return Message containing information about the exception.
+ *
+ */
+ public String getMessage()
+ {
+ StringBuffer sb=new StringBuffer();
+ sb.append(super.getMessage());
+ Throwable cause=getCause();
+
+ if (!noMsg && cause!=null) {
+ sb.append(" [Cause: ");
+ sb.append(cause.toString());
+ sb.append("] ");
+ }
+
+ return sb.toString();
+ }
+
+
+
+
+}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/LocalStrings.properties b/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/LocalStrings.properties
new file mode 100644
index 0000000..edf6d9c
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/util/LocalStrings.properties
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+#The below two are not used
+#password.badalgorithm=Unknown algorithm {0}.
+#password.badformat=Invalid format: {0}
+ssha.badformat=Invalid format: {0}
diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/web/.gitkeep_empty_dir b/nucleus/security/core/src/main/java/com/sun/enterprise/security/web/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/web/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/disable-secure-admin.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/disable-secure-admin.1
new file mode 100644
index 0000000..c4b0ffe
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/disable-secure-admin.1
@@ -0,0 +1,53 @@
+disable-secure-admin(1) asadmin Utility Subcommands disable-secure-admin(1)
+
+NAME
+ disable-secure-admin - disables secure admin if it is already enabled.
+
+SYNOPSIS
+ disable-secure-admin [--help]
+
+DESCRIPTION
+ The disable-secure-admin subcommand disables secure admin if it is
+ already enabled.
+
+ Note
+ +----------------------------------------+
+ | You must restart any running |
+ | servers in the domain after |
+ | you enable or disable secure |
+ | admin. It is simpler to |
+ | enable or disable secure |
+ | admin with only the DAS |
+ | running, then restart the |
+ | DAS, and then start any |
+ | other instances. |
+ +----------------------------------------+
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+EXAMPLES
+ Example 1, Disabling secure admin for a domain
+ The following example shows how to disable secure admin for a
+ domain.
+
+ asadmin> disable-secure-admin
+ server-config
+ default-config
+
+ Command disable-secure-admin executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ enable-secure-admin(1)
+
+ asadmin(1M)
+
+Java EE 8 25 Jun 2011 disable-secure-admin(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/enable-secure-admin.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/enable-secure-admin.1
new file mode 100644
index 0000000..66c6349
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/admin/cli/enable-secure-admin.1
@@ -0,0 +1,89 @@
+enable-secure-admin(1) asadmin Utility Subcommands enable-secure-admin(1)
+
+NAME
+ enable-secure-admin - enables secure admin (if it is not already
+ enabled), optionally changing the alias used for DAS-to-instance admin
+ messages or the alias used for instance-to-DAS admin messages.
+
+SYNOPSIS
+ enable-secure-admin [--help]
+ [--adminalias=alias]
+ [--instancealias=alias]
+
+DESCRIPTION
+ The enable-secure-admin subcommand causes the DAS and the instances in
+ the domain to use SSL certificates for encrypting the messages they
+ send to each other. This subcommand also allows the DAS to accept
+ administration messages from remote admin clients such as the asadmin
+ utility and IDEs.
+
+ Note
+ +----------------------------------------+
+ | You must restart any running |
+ | servers in the domain after |
+ | you enable or disable secure |
+ | admin. It is simpler to |
+ | enable or disable secure |
+ | admin with only the DAS |
+ | running, then restart the |
+ | DAS, and then start any |
+ | other instances. |
+ +----------------------------------------+
+
+ By default, when secure admin is enabled the DAS and the instances use
+ these SSL certificates to authenticate to each other as security
+ "principals" and to authorize admin access. The --asadminalias value
+ indicates to the DAS which SSL certificate it should use to identify
+ itself to the instances. The --instancealias value determines for
+ instances which SSL certificate they should use to identify themselves
+ to the DAS.
+
+ The enable-secure-admin subcommand fails if any administrative user in
+ the domain has a blank password.
+
+ Alternatively, you can use the enable-secure-admin-internal-user
+ subcommand to cause the servers to identify themselves using a secure
+ admin user name and password.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --adminalias
+ The alias that refers to the SSL/TLS certificate on the DAS. This
+ alias is used by the DAS to identify itself to instances. The
+ default value is s1as.
+
+ --instancealias
+ The alias that refers to the SSL/TLS certificate on the instances.
+ This alias is used by the instances to identify themselves to the
+ DAS. The default value is glassfish-instance.
+
+EXAMPLES
+ Example 1, Enabling secure admin for a domain
+ The following example shows how to enable secure admin for a domain
+ using an admin alias adtest and an instance alias intest
+
+ asadmin> enable-secure-admin --adminalias adtest --instancealias intest
+ server-config
+ default-config
+
+ Command enable-secure-admin executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ disable-secure-admin(1)
+
+ enable-secure-admin-principal(1)
+
+ enable-secure-admin-internal-user(1)
+
+ asadmin(1M)
+
+Java EE 8 25 Jun 2011 enable-secure-admin(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/configure-ldap-for-admin.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/configure-ldap-for-admin.1
new file mode 100644
index 0000000..ca3f4ca
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/configure-ldap-for-admin.1
@@ -0,0 +1,44 @@
+configure-ldap-for-admin(1) asadmin Utility Subcommands configure-ldap-for-admin(1)
+
+NAME
+ configure-ldap-for-admin - configures the authentication realm named
+ admin-realm for the given LDAP
+
+SYNOPSIS
+ configure-ldap-for-admin [--help]
+
+DESCRIPTION
+ The configure-ldap-for-admin subcommand configures the authentication
+ realm named admin-realm for the given LDAP. The
+ configure-ldap-for-admin subcommand is interactive. The subcommand
+ prompts the user for the basedn and ldap-group options.
+
+ This command is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+EXAMPLES
+ Example 1, Configuring the LDAP Authentication Realm
+
+ asadmin> configure-ldap-for-admin
+ Enter the value for the basedn option>
+ Enter the value for the ldap-group option>
+ The LDAP Auth Realm admin-realm was configured correctly
+ in admin server's configuration.
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ change-admin-password(1), create-auth-realm(1)create-auth-realm(1),
+ list-auth-realms(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 configure-ldap-for-admin(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-audit-module.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-audit-module.1
new file mode 100644
index 0000000..c22a4b9
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-audit-module.1
@@ -0,0 +1,86 @@
+create-audit-module(1) asadmin Utility Subcommands create-audit-module(1)
+
+NAME
+ create-audit-module - adds an audit module
+
+SYNOPSIS
+ create-audit-module [--help]
+ --classname classname
+ [--property(name=value)[:name=value]*]
+ [--target target]
+ audit_module_name
+
+DESCRIPTION
+ The create-audit-module subcommand adds the named audit module for the
+ Java class that implements the audit capabilities. Audit modules
+ collect and store information on incoming requests (from, for example,
+ servlets and EJB components) and outgoing responses.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --classname
+ The name of the Java class that implements this audit module. If
+ not specified, this option defaults to
+ com.sun.enterprise.security.Audit.
+
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --property
+ Optional keyword-value pairs that specify additional properties for
+ the audit module.
+
+ Audit module properties that are defined by GlassFish Server are as
+ follows:
+
+ auditOn
+ If true, specifies that the audit module is loaded and called
+ by the GlassFish Server audit library at audit points.
+
+ Other available properties are determined by the implementation of
+ the audit module.
+
+ --target
+ Specifies the target on which you are creating the audit module.
+ Valid values are as follows:
+
+ server
+ Creates the audit module for the default server instance server
+ and is the default value.
+
+ configuration_name
+ Creates the audit module for the named configuration.
+
+ cluster_name
+ Creates the audit module for every server instance in the
+ cluster.
+
+ instance_name
+ Creates the audit module for a particular server instance.
+
+OPERANDS
+ audit_module_name
+ The name of this audit module.
+
+EXAMPLES
+ Example 1, Creating an audit module
+
+ asadmin> create-audit-module
+ --classname com.sun.appserv.auditmodule
+ --property defaultuser=admin:Password=admin sampleAuditModule
+ Command create-audit-module executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ delete-audit-module(1), list-audit-modules(1)
+
+ asadmin(1M)
+
+Java EE 8 22 Dec 2010 create-audit-module(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-auth-realm.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-auth-realm.1
new file mode 100644
index 0000000..ecda1da
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-auth-realm.1
@@ -0,0 +1,266 @@
+create-auth-realm(1) asadmin Utility Subcommands create-auth-realm(1)
+
+NAME
+ create-auth-realm - adds the named authentication realm
+
+SYNOPSIS
+ create-auth-realm --classname realm_class [--help] [--property(name=value)[:name=value]*]
+ [--target target_name] auth_realm_name
+
+DESCRIPTION
+ The create-auth-realm subcommand adds the named authentication realm.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target on which you are creating the realm. Valid
+ values are
+
+ server
+ Creates the realm on the default server instance. This is the
+ default value.
+
+ configuration_name
+ Creates the realm in the specified configuration.
+
+ cluster_name
+ Creates the realm on all server instances in the specified
+ cluster.
+
+ instance_name
+ Creates the realm on a specified server instance.
+
+ --classname
+ Java class which implements this realm. These include
+ com.sun.enterprise.security.auth.realm.file.FileRealm,
+ com.sun.enterprise.security.auth.realm.certificate.CertificateRealm,
+ com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm,
+ com.sun.enterprise.security.auth.realm.ldap.LDAPRealm,
+ com.sun.enterprise.security.auth.realm.ldap.PamRealm, and
+ com.sun.enterprise.security.auth.realm.solaris.SolarisRealm, or a
+ custom realm.
+
+ --property
+ Optional attribute name-value pairs for configuring the
+ authentication realm. Authentication realms require
+ provider-specific properties, which vary based on implementation.
+
+ The following properties are common to all of the supported realms,
+ which include FileRealm, CertificateRealm, JDBCRealm, LDAPRealm,
+ PamRealm, and SolarisRealm.
+
+ jaas-context
+ Specifies the Java Authentication and Authorization Service
+ (JAAS) context.
+
+ assign-groups
+ (Optional) If this property is set, its value is taken to be a
+ comma-separated list of group names. All clients who present
+ valid certificates are assigned membership to these groups for
+ the purposes of authorization decisions in the web and EJB
+ containers.
+
+ Specific to each realm, you can specify the following properties.
+
+ * You can specify the following properties for FileRealm:
+
+ file
+ Specifies the file that stores user names, passwords, and
+ group names. The default is domain-dir/config/keyfile.
+
+ * You can specify the following properties for CertificateRealm:
+
+ LoginModule
+ Specifies the name of a JAAS LoginModule to use for
+ performing authentication. To use a JAAS LoginModule, you
+ must first create an implementation of the
+ javax.security.auth.spi.LoginModule interface, and then
+ plug the module into a jaas-context. For more information,
+ see "Custom Authentication of Client Certificate in SSL
+ Mutual Authentication" in Oracle GlassFish Server Security
+ Guide.
+
+ * You can specify the following properties for JDBCRealm:
+
+ datasource-jndi
+ Specifies the jndi-name of the jdbc-resource for the
+ database.
+
+ user-table
+ Specifies the name of the user table in the database.
+
+ user-name-column
+ Specifies the name of the user name column in the
+ database's user table.
+
+ password-column
+ Specifies the name of the password column in the database's
+ user table.
+
+ group-table
+ Specifies the name of the group table in the database.
+
+ group-table
+ Specify the group table for an authentication realm of
+ class JDBCRealm.
+
+ group-name-column
+ Specifies the name of the group name column in the
+ database's group table.
+
+ db-user
+ (Optional) Allows you to specify the database user name in
+ the realm instead of the jdbc-connection-pool. This
+ prevents other applications from looking up the database,
+ getting a connection, and browsing the user table. By
+ default, the jdbc-connection-pool configuration is used.
+
+ db-password
+ (Optional) Allows you to specify the database password in
+ the realm instead of the jdbc-connection-pool. This
+ prevents other applications from looking up the database,
+ getting a connection, and browsing the user table. By
+ default, the jdbc-connection-pool configuration is used.
+
+ group-table
+ Specifies the name of the group table in the database.
+
+ digest-algorithm
+ (Optional) Specifies the digest algorithm. The default is
+ SHA-256. You can use any algorithm supported in the JDK, or
+ none.
+
+ Note
+ +------------------------------------------------------------------------------------------------------+
+ |In versions of GlassFish Server prior |
+ |to 4.0, the default algorithm was MD5. |
+ |If you have applications that depend on |
+ |the MD5 algorithm, you can override the |
+ |default SHA-25 algorithm by using the |
+ |asadmin set subcommand: |
+ | asadmin> set server.security-service.property.default-digest-algorithm=MD5 |
+ | |
+ | You can use the |
+ | asadmin get |
+ | subcommand to |
+ | determine what |
+ | algorithm is |
+ | currently being |
+ | used: |
+ | asadmin> get server.security-service.property.default-digest-algorithm |
+ | |
+ | Also note that, |
+ | to maintain |
+ | backward |
+ | compatibility, |
+ | if an upgrade is |
+ | performed from |
+ | GlassFish Server |
+ | v2.x or v3.0.x |
+ | to GlassFish |
+ | Server 4.0, the |
+ | default |
+ | algorithm is |
+ | automatically |
+ | set to MD5 in |
+ | cases where the |
+ | digest algorithm |
+ | had not been |
+ | explicitly set |
+ | in the older |
+ | GlassFish Server |
+ | version. |
+ +------------------------------------------------------------------------------------------------------+
+
+ digestrealm-password-enc-algorithm
+ (Optional) Specifies the algorithm for encrypting passwords
+ stored in the database.
+
+ Note
+ +---------------------------------------+
+ |It is a security risk not to specify a |
+ |password encryption algorithm. |
+ +---------------------------------------+
+
+ encoding
+ (Optional) Specifies the encoding. Allowed values are Hex
+ and Base64. If digest-algorithm is specified, the default
+ is Hex. If digest-algorithm is not specified, by default no
+ encoding is specified.
+
+ charset
+ (Optional) Specifies the charset for the digest algorithm.
+
+ * You can specify the following properties for LDAPRealm:
+
+ directory
+ Specifies the LDAP URL to your server.
+
+ base-dn
+ Specifies the LDAP base DN for the location of user data.
+ This base DN can be at any level above the user data, since
+ a tree scope search is performed. The smaller the search
+ tree, the better the performance.
+
+ search-filter
+ (Optional) Specifies the search filter to use to find the
+ user. The default is uid=%s (%s expands to the subject
+ name).
+
+ group-base-dn
+ (Optional) Specifies the base DN for the location of groups
+ data. By default, it is same as the base-dn, but it can be
+ tuned, if necessary.
+
+ group-search-filter
+ (Optional) Specifies the search filter to find group
+ memberships for the user. The default is uniquemember=%d
+ (%d expands to the user elementDN).
+
+ group-target
+ (Optional) Specifies the LDAP attribute name that contains
+ group name entries. The default is CN.
+
+ search-bind-dn
+ (Optional) Specifies an optional DN used to authenticate to
+ the directory for performing the search-filter lookup. Only
+ required for directories that do not allow anonymous
+ search.
+
+ search-bind-password
+ (Optional) Specifies the LDAP password for the DN given in
+ search-bind-dn.
+
+OPERANDS
+ auth_realm_name
+ A short name for the realm. This name is used to refer to the realm
+ from, for example, web.xml.
+
+EXAMPLES
+ Example 1, Creating a New Authentication Realm
+ This example creates a new file realm.
+
+ asadmin> create-auth-realm
+ --classname com.sun.enterprise.security.auth.realm.file.FileRealm
+ --property file=${com.sun.aas.instanceRoot}/config/
+ admin-keyfile:jaas-context=fileRealm file
+ Command create-auth-realm executed successfully
+ Where file is the authentication realm created.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ delete-auth-realm(1), list-auth-realms(1)
+
+ asadmin(1M)
+
+Java EE 8 20 Sep 2010 create-auth-realm(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-file-user.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-file-user.1
new file mode 100644
index 0000000..937d115
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-file-user.1
@@ -0,0 +1,73 @@
+create-file-user(1) asadmin Utility Subcommands create-file-user(1)
+
+NAME
+ create-file-user - creates a new file user
+
+SYNOPSIS
+ create-file-user [--help] [--authrealmnameauth_realm_name]
+ [--target target
+ [--groups user_groups[:user_groups]*] user_name
+
+DESCRIPTION
+ The create-file-user subcommand creates an entry in the keyfile with
+ the specified username, password, and groups. Multiple groups can be
+ created by separating them with a colon (:). If auth_realm_name is not
+ specified, an entry is created in the keyfile for the default realm. If
+ auth_realm_name is specified, an entry is created in the keyfile using
+ the auth_realm_name.
+
+ You can use the --passwordfile option of the asadmin(1M) command to
+ specify the password for the user. The password file entry must be of
+ the form AS_ADMIN_USERPASSWORD=user-password.
+
+ If a password is not provided, this subcommand fails if secure
+ administration is enabled and the user being created is an
+ administrative user.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ This is the name of the target on which the command operates. The
+ valid targets are config, instance, cluster, or server. By default,
+ the target is the server.
+
+ --groups
+ This is the group associated with this file user.
+
+ --authrealmname
+ The name of the realm in which the new user is created. If you do
+ not specify this option, the user is created in the "file" realm.
+
+OPERANDS
+ user_name
+ This is the name of file user to be created.
+
+EXAMPLES
+ Example 1, Creating a User in the File Realm
+ This example creates a file realm user named sample_user. It is
+ assumed that an authentication realm has already been created using
+ the create-auth-realm subcommand.
+
+ asadmin> create-file-user
+ --groups staff:manager
+ --authrealmname auth-realm1 sample_user
+ Command create-file-user executed successfully
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ create-auth-realm(1), delete-file-user(1), list-file-users(1),
+ update-file-user(1), list-file-groups(1)
+
+ asadmin(1M)
+
+Java EE 8 03 June 2011 create-file-user(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-jacc-provider.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-jacc-provider.1
new file mode 100644
index 0000000..ca6f480
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-jacc-provider.1
@@ -0,0 +1,116 @@
+create-jacc-provider(1) asadmin Utility Subcommands create-jacc-provider(1)
+
+NAME
+ create-jacc-provider - enables administrators to create a JACC provider
+ that can be used by third-party authorization modules for applications
+ running in GlassFish Server
+
+SYNOPSIS
+ create-jacc-provider [--help]
+ [--policyproviderclass pol-provider-class]
+ [--policyconfigfactoryclass pc-factory-class]
+ [--property name=value)[:name=value]*]
+ [--target target] jacc-provider-name
+
+DESCRIPTION
+ The create-jacc-provider subcommand creates a JSR-115—compliant Java
+ Authorization Contract for Containers (JACC) provider that can be used
+ for authorization of applications running in GlassFish Server. The JACC
+ provider is created as a jacc-provider element within the
+ security-service element in the domain's domain.xml file.
+
+ The default GlassFish Server installation includes two JACC providers,
+ named default and simple. Any JACC providers created with the
+ create-jacc-provider subcommand are in addition to these two default
+ providers. The default GlassFish Server JACC providers implement a
+ simple, file-based authorization engine that complies with the JACC
+ specification. The create-jacc-provider subcommand makes it possible to
+ specify additional third-party JACC providers.
+
+ You can create any number of JACC providers within the security-service
+ element, but the GlassFish Server runtime uses only one of them at any
+ given time. The jacc-provider element in the security-service element
+ points to the name of the provider that is currently in use by
+ GlassFish Server. If you change this element to point to a different
+ JACC provider, restart GlassFish Server.
+
+ This command is supported in remote mode only.
+
+OPTIONS
+ If an option has a short option name, then the short option precedes
+ the long option name. Short options have one dash whereas long options
+ have two dashes.
+
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --policyproviderclass
+ Specifies the fully qualified class name for the
+ javax.security.jacc.policy.provider that implements the
+ java.security.Policy.
+
+ --policyconfigfactoryclass
+ Specifies the fully qualified class name for the
+ javax.security.jacc.PolicyConfigurationFactory.provider that
+ implements the provider-specific
+ javax.security.jacc.PolicyConfigurationFactory.
+
+ --property
+ Optional attribute name/value pairs for configuring the JACC
+ provider. The following properties are available:
+
+ repository
+ The directory containing the JACC policy file. For the default
+ GlassFish Server JACC provider, the default directory is
+ ${com.sun.aas.instanceRoot}/generated/policy. This property is
+ not defined by default for the simple GlassFish Server JACC
+ provider.
+
+ --target
+ Specifies the target for which you are creating the JACC provider.
+ The following values are valid:
+
+ server
+ Creates the JACC provider on the default server instance. This
+ is the default value.
+
+ configuration_name
+ Creates the JACC provider in the specified configuration.
+
+ cluster_name
+ Creates the JACC provider on all server instances in the
+ specified cluster.
+
+ instance_name
+ Creates the JACC provider on a specified server instance.
+
+OPERANDS
+ jacc-provider-name
+ The name of the provider used to reference the jacc-provider
+ element in domain.xml.
+
+EXAMPLES
+ Example 1, Creating a JACC Provider
+ The following example shows how to create a JACC provider named
+ testJACC on the default server target.
+
+ asadmin> create-jacc-provider
+ --policyproviderclass com.sun.enterprise.security.provider.PolicyWrapper
+ --policyconfigfactoryclass com.sun.enterprise.security.provider.PolicyConfigurationFactoryImpl
+ testJACC
+
+ Command create-jacc-provider executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ delete-jacc-provider(1), list-jacc-providers(1)
+
+ asadmin(1M)
+
+Java EE 8 14 Jun 2011 create-jacc-provider(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-message-security-provider.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-message-security-provider.1
new file mode 100644
index 0000000..132db5d
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-message-security-provider.1
@@ -0,0 +1,169 @@
+create-message-security-provider(1) asadmin Utility Subcommands create-message-security-provider(1)
+
+NAME
+ create-message-security-provider - enables administrators to create a
+ message security provider, which specifies how SOAP messages will be
+ secured.
+
+SYNOPSIS
+ create-message-security-provider [--help]
+ [--target target]
+ --classname provider_class
+ [--layer message_layer] [--providertype provider_type]
+ [--requestauthsource request_auth_source ]
+ [--requestauthrecipient request_auth_recipient ]
+ [--responseauthsource response_auth_source ]
+ [--responseauthrecipient response_auth_recipient ]
+ [--isdefaultprovider] [--property name=value[:name=value]*]
+ provider_name
+
+DESCRIPTION
+ The create-message-security-provider subcommand enables the
+ administrator to create a message security provider for the security
+ service which specifies how SOAP messages will be secured.
+
+ This command is supported in remote mode only.
+
+OPTIONS
+ If an option has a short option name, then the short option precedes
+ the long option name. Short options have one dash whereas long options
+ have two dashes.
+
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target for which you are creating the message
+ security provider. The following values are valid:
+
+ server
+ Creates the provider for the default server instance server and
+ is the default value.
+
+ domain
+ Creates the provider for the domain.
+
+ cluster_name
+ Creates the provider for every server instance in the cluster.
+
+ instance_name
+ Creates the provider for a particular sever instance.
+
+ --classname
+ Defines the Java implementation class of the provider. Client
+ authentication providers must implement the com.sun.enterprise.
+ security.jauth.ClientAuthModule interface. Server-side providers
+ must implement the com.sun.enterprise.security
+ jauth.ServerAuthModule interface. A provider may implement both
+ interfaces, but it must implement the interface corresponding to
+ its provider type.
+
+ --layer
+ The message-layer entity used to define the value of the auth-layer
+ attribute of message-security-config elements. The default is
+ HttpServlet. Another option is SOAP.
+
+ --providertype
+ Establishes whether the provider is to be used as client
+ authentication provider, server authentication provider, or both.
+ Valid options for this property include client, server, or
+ client-server.
+
+ --requestauthsource
+ The auth-source attribute defines a requirement for message-layer
+ sender authentication (e.g. username password) or content
+ authentication (e.g. digital signature) to be applied to request
+ messages. Possible values are sender or content. When this argument
+ is not specified, source authentication of the request is not
+ required.
+
+ --requestauthrecipient
+ The auth-recipient attribute defines a requirement for
+ message-layer authentication of the receiver of a message to its
+ sender (e.g. by XML encryption). Possible values are before-content
+ or after-content. The default value is after-content.
+
+ --responseauthsource
+ The auth-source attribute defines a requirement for message-layer
+ sender authentication (e.g. username password) or content
+ authentication (e.g. digital signature) to be applied to response
+ messages. Possible values are sender or content. When this option
+ is not specified, source authentication of the response is not
+ required.
+
+ --responseauthrecipient
+ The auth-recipient attribute defines a requirement for
+ message-layer authentication of the receiver of the response
+ message to its sender (e.g. by XML encryption). Possible values are
+ before-content or after-content. The default value is
+ after-content.
+
+ --isdefaultprovider
+ The default-provider attribute is used to designate the provider as
+ the default provider (at the layer) of the type or types identified
+ by the providertype argument. There is no default associated with
+ this option.
+
+ --property
+ Use this property to pass provider-specific property values to the
+ provider when it is initialized. Properties passed in this way
+ might include key aliases to be used by the provider to get keys
+ from keystores, signing, canonicalization, encryption algorithms,
+ etc.
+
+ The following properties may be set:
+
+ security.config
+ Specifies the location of the message security configuration
+ file. To point to a configuration file in the domain-dir/config
+ directory, use the system property
+ ${com.sun.aas.instanceRoot}/config/, for example:
+ ${com.sun.aas.instanceRoot}/config/wss-server-config-1.0.xml.
+ The default is domain-dir/config/ wss-serverconfig-1.0.xml.
+
+ debug
+ If true, enables dumping of server provider debug messages to
+ the server log. The default is false.
+
+ dynamic.username. password
+ If true, signals the provider runtime to collect the user name
+ and password from the CallbackHandler for each request. If
+ false, the user name and password for wsse:UsernameToken(s) is
+ collected once, during module initialization. This property is
+ only applicable for a ClientAuthModule. The default is false.
+
+ encryption.key.alias
+ Specifies the encryption key used by the provider. The key is
+ identified by its keystore alias. The default value is s1as.
+
+ signature.key.alias
+ Specifies the signature key used by the provider. The key is
+ identified by its keystore alias. The default value is s1as.
+
+OPERANDS
+ provider_name
+ The name of the provider used to reference the provider-config
+ element.
+
+EXAMPLES
+ Example 1, Creating a Message Security Provider
+ The following example shows how to create a message security
+ provider for a client.
+
+ asadmin> create-message-security-provider
+ --classname com.sun.enterprise.security.jauth.ClientAuthModule
+ --providertype client mySecurityProvider
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ delete-message-security-provider(1), list-message-security-providers(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 create-message-security-provider(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-password-alias.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-password-alias.1
new file mode 100644
index 0000000..465f32f
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/create-password-alias.1
@@ -0,0 +1,72 @@
+create-password-alias(1) asadmin Utility Subcommands create-password-alias(1)
+
+NAME
+ create-password-alias - creates a password alias
+
+SYNOPSIS
+ create-password-alias [--help]
+ aliasname
+
+DESCRIPTION
+ The create-password-alias subcommand creates an alias for a password.
+ An alias is a token of the form ${ALIAS=aliasname}. The password that
+ corresponds to the alias name is stored in an encrypted form.
+
+ The create-password-alias subcommand can be run interactively or
+ noninteractively.
+
+ * When run interactively, the subcommand prompts the user for the
+ alias password and to confirm the alias password.
+
+ * When run noninteractively, the subcommand reads the alias password
+ from a file that is passed through the --passwordfile option of the
+ asadmin(1M) utility. The file must contain an entry of the form
+ AS_ADMIN_ALIASPASSWORD=alias-password, where alias-password is the
+ alias password. The noninteractive form of this command is suitable
+ for use in scripts.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ aliasname
+ Your choice of name for the password alias.
+
+EXAMPLES
+ Example 1, Creating a Password Alias Interactively
+ This example creates the password alias jmspassword-alias
+ interactively.
+
+ asadmin> create-password-alias jmspassword-alias
+ Enter the alias password>
+ Enter the alias password again>
+ Command create-password-alias executed successfully.
+
+ Example 2, Creating a Password Alias Noninteractively
+ This example uses the --passwordfile option of the asadmin utility
+ to create the password alias winuser noninteractively.
+
+ $ asadmin --passwordfile aspwfile.txt create-password-alias winuser
+ Command create-password-alias executed successfully.
+ The file aspwfile.txt contains the following entry to specify the
+ alias password:
+
+ AS_ADMIN_ALIASPASSWORD=sp@rky
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ delete-password-alias(1), list-password-aliases(1),
+ update-password-alias(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 create-password-alias(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-audit-module.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-audit-module.1
new file mode 100644
index 0000000..8da40b2
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-audit-module.1
@@ -0,0 +1,59 @@
+delete-audit-module(1) asadmin Utility Subcommands delete-audit-module(1)
+
+NAME
+ delete-audit-module - removes the named audit-module
+
+SYNOPSIS
+ delete-audit-module [--help]
+ [--target target]
+ audit_module_name
+
+DESCRIPTION
+ This subcommand removes the named audit module. This subcommand is
+ supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target on which you are deleting the audit module.
+ Valid values are as follows:
+
+ server
+ Deletes the audit module for the default server instance server
+ and is the default value.
+
+ configuration_name
+ Deletes the audit module for the named configuration.
+
+ cluster_name
+ Deletes the audit module for every server instance in the
+ cluster.
+
+ instance_name
+ Deletes the audit module for a particular server instance.
+
+OPERANDS
+ audit_module_name
+ The name of the audit module to be deleted.
+
+EXAMPLES
+ Example 1, Deleting an audit module
+
+ asadmin> delete-audit-module sampleAuditModule
+ Command delete-audit-module executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-audit-module(1), list-audit-modules(1)
+
+ asadmin(1M)
+
+Java EE 8 22 Dec 2010 delete-audit-module(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-auth-realm.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-auth-realm.1
new file mode 100644
index 0000000..9258f93
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-auth-realm.1
@@ -0,0 +1,59 @@
+delete-auth-realm(1) asadmin Utility Subcommands delete-auth-realm(1)
+
+NAME
+ delete-auth-realm - removes the named authentication realm
+
+SYNOPSIS
+ delete-auth-realm [--help]
+ [--target target]
+ auth_realm-name
+
+DESCRIPTION
+ The delete-auth-realm subcommand removes the named authentication
+ realm. This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target on which you are deleting the authentication
+ realm. Valid values are
+
+ server
+ Deletes the realm for the default server instance server and is
+ the default value.
+
+ configuration_name
+ Deletes the realm for the named configuration.
+
+ cluster_name
+ Deletes the realm for every server instance in the cluster.
+
+ instance_name
+ Deletes the realm for a particular server instance.
+
+OPERANDS
+ auth_realm_name
+ Name of the realm to be deleted.
+
+EXAMPLES
+ Example 1, Deleting an Authentication Realm
+ This example deletes the authentication realm db.
+
+ asadmin> delete-auth-realm db
+ Command delete-auth-realm executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-auth-realm(1), list-auth-realms(1)
+
+ asadmin(1M)
+
+Java EE 8 22 Dec 2010 delete-auth-realm(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-file-user.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-file-user.1
new file mode 100644
index 0000000..68a245f
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-file-user.1
@@ -0,0 +1,67 @@
+delete-file-user(1) asadmin Utility Subcommands delete-file-user(1)
+
+NAME
+ delete-file-user - removes the named file user
+
+SYNOPSIS
+ delete-file-user [--help][--authrealmname auth_realm_name]
+ [--target target]
+ username
+
+DESCRIPTION
+ The delete-file-user subcommand deletes the entry in the keyfile for
+ the specified username.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --authrealmname
+ The name of the authentication realm with which the user was
+ created.
+
+ --target
+ This is the name of the target on which the command operates. The
+ valid targets are:
+
+ server
+ Deletes the file user on the default server instance. This is
+ the default value
+
+ domain
+ Deletes the file user in the domain.
+
+ cluster_name
+ Deletes the file user from every server instance in the
+ cluster.
+
+ instance_name
+ Deletes the file user from a particular server instance.
+
+OPERANDS
+ username
+ This is the name of file user to be deleted.
+
+EXAMPLES
+ Example 1, Deleting a User From a File Realm
+ The following example shows how to delete user named sample_user
+ from a file realm.
+
+ asadmin> delete-file-user
+ sample_user
+ Command delete-file-user executed successfully
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ create-file-user(1), list-file-users(1), update-file-user(1),
+ list-file-groups(1)
+
+ asadmin(1M)
+
+Java EE 8 01 December 2010 delete-file-user(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-jacc-provider.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-jacc-provider.1
new file mode 100644
index 0000000..a32e3e3
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-jacc-provider.1
@@ -0,0 +1,84 @@
+delete-jacc-provider(1) asadmin Utility Subcommands delete-jacc-provider(1)
+
+NAME
+ delete-jacc-provider - enables administrators to delete JACC providers
+ defined for a domain
+
+SYNOPSIS
+ delete-jacc-provider [--help]
+ [--target target] jacc-provider-name
+
+DESCRIPTION
+ The delete-jacc-provider subcommand enables administrators to delete
+ JACC providers defined for a domain. JACC providers are defined as
+ jacc-provider elements in the security-service element in the domain's
+ domain.xml file. JACC providers can be created using the GlassFish
+ Server Admin Console or the create-jacc-provider subcommand.
+
+ The default GlassFish Server installation includes two JACC providers,
+ named default and simple. These default providers should not be
+ deleted.
+
+ The JACC provider used byGlassFish Server for authorization is
+ identified by the jacc-provider element of security-service in
+ domain.xml. Therefore, if you delete the jacc-provider provider, make
+ sure you change jacc-provider to the name of some other JACC provider
+ that exists under security-service.
+
+ If you change the jacc-provider element to point to a different JACC
+ provider, you must restart GlassFish Server.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ If an option has a short option name, then the short option precedes
+ the long option name. Short options have one dash whereas long options
+ have two dashes.
+
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target from which you are deleting the JACC provider.
+ The following values are valid:
+
+ server
+ Deletes the JACC provider on the default server instance. This
+ is the default value.
+
+ configuration_name
+ Deletes the JACC provider in the specified configuration.
+
+ cluster_name
+ Deletes the JACC provider on all server instances in the
+ specified cluster.
+
+ instance_name
+ Deletes the JACC provider on a specified server instance.
+
+OPERANDS
+ jacc-provider-name
+ The name of the JACC provider to be deleted.
+
+EXAMPLES
+ Example 1, Deleting a JACC provider
+ The following example shows how to delete a JACC provider named
+ testJACC from the default domain.
+
+ asadmin> delete-jacc-provider testJACC
+
+ Command delete-jacc-provider executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ create-jacc-provider(1), list-jacc-providers(1)
+
+ asadmin(1M)
+
+Java EE 8 14 Jun 2011 delete-jacc-provider(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-message-security-provider.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-message-security-provider.1
new file mode 100644
index 0000000..a8e914b
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-message-security-provider.1
@@ -0,0 +1,85 @@
+delete-message-security-provider(1) asadmin Utility Subcommands delete-message-security-provider(1)
+
+NAME
+ delete-message-security-provider - enables administrators to delete a
+ message security provider
+
+SYNOPSIS
+ delete-message-security-provider [--help] [--target target]
+ --layer message_layer
+ provider_name
+
+DESCRIPTION
+ The delete-message-security-provider subcommand enables administrators
+ to delete a message security provider.
+
+ In terms of what happens when this subcommand is run, the
+ provider-config sub-element for the given message layer
+ (message-security-config element of domain.xml is deleted. The
+ domain.xmlfile specifies parameters and properties to the GlassFish
+ Server). The options specified in the list below apply to attributes
+ within the message-security-config and provider-config sub-elements of
+ the domain.xml file.
+
+ If the message-layer (message-security-config attribute) does not
+ exist, it is created, and then the provider-config is created under it.
+
+ This command is supported in remote mode only.
+
+OPTIONS
+ If an option has a short option name, then the short option precedes
+ the long option name. Short options have one dash whereas long options
+ have two dashes.
+
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target from which you are deleting the message
+ security provider. Valid values are
+
+ server
+ Deletes the message security provider from the default server
+ instance server and is the default value
+
+ domain
+ Deletes the message security provider from the domain.
+
+ cluster_name
+ Deletes the message security provider from every server
+ instance in the cluster.
+
+ instance_name
+ Deletes the message security provider from a particular sever
+ instance.
+
+ --layer
+ The message-layer from which the provider has to be deleted. The
+ default value is HttpServlet.
+
+OPERANDS
+ provider_name
+ The name of the provider used to reference the provider-config
+ element.
+
+EXAMPLES
+ Example 1, Deleting a message security provider
+ The following example shows how to delete a message security
+ provider for a client.
+
+ asadmin> delete-message-security-provider
+ --layer SOAP mySecurityProvider
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-message-security-provider(1), list-message-security-providers(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 delete-message-security-provider(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-password-alias.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-password-alias.1
new file mode 100644
index 0000000..0865934
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/delete-password-alias.1
@@ -0,0 +1,42 @@
+delete-password-alias(1) asadmin Utility Subcommands delete-password-alias(1)
+
+NAME
+ delete-password-alias - deletes a password alias
+
+SYNOPSIS
+ delete-password-alias [--help]
+ aliasname
+
+DESCRIPTION
+ This subcommand deletes a password alias.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ aliasname
+ This is the name of the substitute password as it appears in
+ domain.xml.
+
+EXAMPLES
+ Example 1, Deleting a Password Alias
+
+ asadmin>delete-password-alias
+ jmspassword-alias
+ Command delete-password-alias executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-password-alias(1), list-password-aliases(1),
+ update-password-alias(1)
+
+ asadmin(1M)
+
+Java EE 8 28 August 2009 delete-password-alias(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-audit-modules.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-audit-modules.1
new file mode 100644
index 0000000..98cba1f
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-audit-modules.1
@@ -0,0 +1,56 @@
+list-audit-modules(1) asadmin Utility Subcommands list-audit-modules(1)
+
+NAME
+ list-audit-modules - gets all audit modules and displays them
+
+SYNOPSIS
+ list-audit-modules [--help] [target]
+
+DESCRIPTION
+ The list-audit-modules subcommand lists all the audit modules. This
+ subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ target
+ Specifies the target on which you are listing the audit modules.
+ Valid values are as follows:
+
+ server
+ Lists the audit modules for the default server instance server
+ and is the default value.
+
+ configuration_name
+ Lists the audit modules for the named configuration.
+
+ cluster_name
+ Lists the audit modules for every server instance in the
+ cluster.
+
+ instance_name
+ Lists the audit modules for a particular server instance.
+
+EXAMPLES
+ Example 1, Listing Audit Modules
+
+ asadmin> list-audit-modules
+ sampleAuditModule1
+ sampleAuditModule2
+ Command list-audit-modules executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-audit-module(1), delete-audit-module(1)
+
+ asadmin(1M)
+
+Java EE 8 22 Dec 2010 list-audit-modules(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-auth-realms.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-auth-realms.1
new file mode 100644
index 0000000..9f47df6
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-auth-realms.1
@@ -0,0 +1,59 @@
+list-auth-realms(1) asadmin Utility Subcommands list-auth-realms(1)
+
+NAME
+ list-auth-realms - lists the authentication realms
+
+SYNOPSIS
+ list-auth-realms [--help] [target]
+
+DESCRIPTION
+ The list-auth-realms subcommand lists the authentication realms. This
+ subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ target
+ The name of the target for which you want to list the
+ authentication realms.
+
+ server
+ Lists the realms for the default server instance server and is
+ the default value.
+
+ configuration_name
+ Lists the realms for the named configuration.
+
+ cluster_name
+ Lists the realms for every server instance in the cluster.
+
+ instance_name
+ Lists the realms for a particular server instance.
+
+EXAMPLES
+ Example 1, Listing authentication realms
+
+ asadmin> list-auth-realms
+ file
+ ldap
+ certificate
+ db
+ Command list-auth-realms executed successfully
+ Where file, ldap, certificate, and db are the available
+ authentication realms.
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-auth-realm(1), delete-auth-realm(1)
+
+ asadmin(1M)
+
+Java EE 8 22 Dec 2010 list-auth-realms(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-groups.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-groups.1
new file mode 100644
index 0000000..4b2f840
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-groups.1
@@ -0,0 +1,66 @@
+list-file-groups(1) asadmin Utility Subcommands list-file-groups(1)
+
+NAME
+ list-file-groups - lists file groups
+
+SYNOPSIS
+ list-file-groups [--help] [--name username] [--authrealmname auth_realm_name]
+ [--target target]
+
+DESCRIPTION
+ The list-file-groups subcommand lists the file users and groups
+ supported by the file realm authentication. This subcommand lists
+ available groups in the file user. If the --name option is not
+ specified, all groups are listed.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --name
+ Identifies the name of the file user for whom the groups will be
+ listed.
+
+ --authrealmname
+ The name of the authentication realm for which to list available
+ groups.
+
+ --target
+ This option specifies which configurations you can list. Valid
+ targets are:
+
+ server
+ Lists the file groups in the current server. This is the
+ default value.
+
+ cluster_name
+ Lists the file groups in a cluster.
+
+ instance_name
+ Lists the file groups for a particular instance.
+
+EXAMPLES
+ Example 1, Listing Groups in all File Realms
+ This example list all file realm groups defined for the server.
+
+ asadmin> list-file-groups
+ staff
+ manager
+ Command list-file-groups executed successfully
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ delete-file-user(1), update-file-user(1), create-file-user(1),
+ list-file-users(1)
+
+ asadmin(1M)
+
+Java EE 8 01 December 2010 list-file-groups(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-users.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-users.1
new file mode 100644
index 0000000..b09c42c
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-file-users.1
@@ -0,0 +1,63 @@
+list-file-users(1) asadmin Utility Subcommands list-file-users(1)
+
+NAME
+ list-file-users - lists the file users
+
+SYNOPSIS
+ list-file-users [--help] [--authrealmname auth_realm_name] [target]
+
+DESCRIPTION
+ The list-file-users subcommand displays a list of file users supported
+ by file realm authentication.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --authrealmname
+ Lists only the users in the specified authentication realm.
+
+OPERANDS
+ target
+ Specifies the target for which you want to list file users. The
+ following values are valid:
+
+ server
+ Lists the file users on the default server instance. This is
+ the default value.
+
+ configuration_name
+ Lists the file users in the specified configuration.
+
+ cluster_name
+ Lists the file users on all server instances in the specified
+ cluster.
+
+ instance_name
+ Lists the file users on a specified server instance.
+
+EXAMPLES
+ Example 1, Listing Users in a Specific File Realm
+ The following example lists the users in the file realm named
+ sample_file_realm.
+
+ asadmin> list-file-users --authrealmname sample_file_realm
+ sample_user05
+ sample_user08
+ sample_user12
+ Command list-file-users executed successfully
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ create-file-user(1), delete-file-user(1), update-file-user(1),
+ list-file-groups(1)
+
+ asadmin(1M)
+
+Java EE 8 21 Jun 2011 list-file-users(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-jacc-providers.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-jacc-providers.1
new file mode 100644
index 0000000..1331c7e
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-jacc-providers.1
@@ -0,0 +1,66 @@
+list-jacc-providers(1) asadmin Utility Subcommands list-jacc-providers(1)
+
+NAME
+ list-jacc-providers - enables administrators to list JACC providers
+ defined for a domain
+
+SYNOPSIS
+ list-jacc-providers [--help] [target]
+
+DESCRIPTION
+ The list-jacc-providers subcommand enables administrators to list the
+ JACC providers defined for a domain. JACC providers are defined as
+ jacc-provider elements in the security-service element in the domain's
+ domain.xml file. JACC providers can be created using the GlassFish
+ Server Admin Console or the create-jacc-provider subcommand.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ target
+ Specifies the target for which you want to list JACC providers. The
+ following values are valid:
+
+ server
+ Lists the JACC providers on the default server instance. This
+ is the default value.
+
+ configuration_name
+ Lists the JACC providers in the specified configuration.
+
+ cluster_name
+ Lists the JACC providers on all server instances in the
+ specified cluster.
+
+ instance_name
+ Lists the JACC providers on a specified server instance.
+
+EXAMPLES
+ Example 1, Listing JACC providers
+ The following example shows how to list JACC providers for the
+ default domain.
+
+ asadmin> list-jacc-providers
+ default
+ simple
+ testJACC
+
+ Command list-jacc-providers executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ create-jacc-provider(1), delete-jacc-provider(1)
+
+ asadmin(1M)
+
+Java EE 8 21 Jun 2011 list-jacc-providers(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-message-security-providers.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-message-security-providers.1
new file mode 100644
index 0000000..9d065ab
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-message-security-providers.1
@@ -0,0 +1,72 @@
+list-message-security-providers(1) asadmin Utility Subcommands list-message-security-providers(1)
+
+NAME
+ list-message-security-providers - lists all security message providers
+ for the given message layer
+
+SYNOPSIS
+ list-message-security-providers [--help]
+ --layer message_layer
+ [target]
+
+DESCRIPTION
+ The list-message-security-providers subcommand enables administrators
+ to list all security message providers (provider-config sub-elements)
+ for the given message layer (message-security-config element of
+ domain.xml).
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --layer
+ The message-layer for which the provider has to be listed. The
+ default value is HttpServlet.
+
+OPERANDS
+ target
+ Restricts the listing to message security providers for a specific
+ target. Valid values include:
+
+ server
+ Lists providers for the default server instance server and is
+ the default value.
+
+ domain
+ Lists providers for the domain.
+
+ cluster
+ Lists providers for the server instances in the cluster.
+
+ instance
+ Lists providers for a particular server instance.
+
+EXAMPLES
+ Example 1, Listing message security providers
+ The following example shows how to list message security providers
+ for a message layer.
+
+ asadmin> list-message-security-providers
+ --layer SOAP
+ XWS_ClientProvider
+ ClientProvider
+ XWS_ServerProvider
+ ServerProvider
+ Command list-message-security-providers executed successfully.
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ create-message-security-provider(1),
+ delete-message-security-provider(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 list-message-security-providers(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-password-aliases.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-password-aliases.1
new file mode 100644
index 0000000..19057ba
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-password-aliases.1
@@ -0,0 +1,36 @@
+list-password-aliases(1) asadmin Utility Subcommands list-password-aliases(1)
+
+NAME
+ list-password-aliases - lists all password aliases
+
+SYNOPSIS
+ list-password-aliases [--help]
+
+DESCRIPTION
+ Thissubcommand lists all of the password aliases.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+EXAMPLES
+ Example 1, Listing all password aliases
+
+ asadmin> list-password-aliases
+ jmspassword-alias
+ Command list-password-aliases executed successfully
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ delete-password-alias(1), update-password-alias(1),
+ create-password-alias(1)
+
+ asadmin(1M)
+
+Java EE 8 28 August 2009 list-password-aliases(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-supported-cipher-suites.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-supported-cipher-suites.1
new file mode 100644
index 0000000..33b4803
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/list-supported-cipher-suites.1
@@ -0,0 +1,85 @@
+list-supported-cipher-suites(1) asadmin Utility Subcommands list-supported-cipher-suites(1)
+
+NAME
+ list-supported-cipher-suites - enables administrators to list the
+ cipher suites that are supported and available to a specified GlassFish
+ Server target
+
+SYNOPSIS
+ list-supported-cipher-suites [--help] [--target target]
+
+DESCRIPTION
+ The list-supported-cipher-suites subcommand enables administrators to
+ list the cipher suites that are supported and available to a specified
+ GlassFish Server target. The cipher suites that may be available in
+ addition to the default SSL/TLS providers that are bundled with
+ GlassFish Server packages will vary depending on the third-party
+ provider.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --target
+ Specifies the target for which you want to list cipher suites. The
+ following values are valid:
+
+ server
+ Lists the cipher suites for the default server instance. This
+ is the default value.
+
+ configuration_name
+ Lists the cipher suites for the specified configuration.
+
+ cluster_name
+ Lists the cipher suites for all server instances in the
+ specified cluster.
+
+ instance_name
+ Lists the cipher suites for a specified server instance.
+
+EXAMPLES
+ Example 1, Listing cipher suites
+ The following example shows how to list cipher suites for the
+ default domain.
+
+ asadmin> list-supported-cipher-suites
+ SSL_RSA_WITH_RC4_128_MD5
+ SSL_RSA_WITH_RC4_128_SHA
+ TLS_RSA_WITH_AES_128_CBC_SHA
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+ SSL_RSA_WITH_DES_CBC_SHA
+ SSL_DHE_RSA_WITH_DES_CBC_SHA
+ SSL_DHE_DSS_WITH_DES_CBC_SHA
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5
+ SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
+ SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+ SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+ SSL_RSA_WITH_NULL_MD5
+ SSL_RSA_WITH_NULL_SHA
+ SSL_DH_anon_WITH_RC4_128_MD5
+ TLS_DH_anon_WITH_AES_128_CBC_SHA
+ SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
+ SSL_DH_anon_WITH_DES_CBC_SHA
+ SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
+ SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+
+ Command list-supported-cipher-suites executed successfully.
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 list-supported-cipher-suites(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-file-user.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-file-user.1
new file mode 100644
index 0000000..72b51e1
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-file-user.1
@@ -0,0 +1,72 @@
+update-file-user(1) asadmin Utility Subcommands update-file-user(1)
+
+NAME
+ update-file-user - updates a current file user as specified
+
+SYNOPSIS
+ update-file-user [--help] [--groups user_groups[:user_groups]*]
+ [--target target
+ [--authrealmname authrealm_name]
+ username
+
+DESCRIPTION
+ Th update-file-user subcommand updates an existing entry in the keyfile
+ using the specified user name, password and groups. Multiple groups can
+ be entered by separating them, with a colon (:).
+
+ If a new password is not provided, this subcommand fails if secure
+ administration is enabled and the user being updated is an
+ administrative user.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+ --groups
+ This is the name of the group to which the file user belongs.
+
+ --authrealmname
+ Name of the authentication realm where the user to be updated can
+ be found.
+
+ --target
+ This option helps specify the target on which you are updating a
+ file user. Valid values are:
+
+ server
+ Updates the file user in the default server instance. This is
+ the default value.
+
+ cluster_name
+ Updates the file user on every server instance in the cluster.
+
+ instance_name
+ Updates the file user on a specified sever instance.
+
+OPERANDS
+ username
+ This is the name of the file user to be updated.
+
+EXAMPLES
+ Example 1, Updating a User's Information in a File Realm
+ The following example updates information for a file realm user
+ named sample_user.
+
+ asadmin> update-file-user
+ --groups staff:manager:engineer sample_user
+ Command update-file-user executed successfully
+
+EXIT STATUS
+ 0
+ subcommand executed successfully
+
+ 1
+ error in executing the subcommand
+
+SEE ALSO
+ delete-file-user(1), list-file-users(1), create-file-user(1),
+ list-file-groups(1)
+
+ asadmin(1M)
+
+Java EE 8 01 December 2010 update-file-user(1)
diff --git a/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-password-alias.1 b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-password-alias.1
new file mode 100644
index 0000000..5102e7e
--- /dev/null
+++ b/nucleus/security/core/src/main/manpages/com/sun/enterprise/security/cli/update-password-alias.1
@@ -0,0 +1,50 @@
+update-password-alias(1) asadmin Utility Subcommands update-password-alias(1)
+
+NAME
+ update-password-alias - updates a password alias
+
+SYNOPSIS
+ update-password-alias [--help]
+ aliasname
+
+DESCRIPTION
+ This subcommand updates the password alias IDs in the named target. An
+ alias is a token of the form ${ALIAS=password-alias-password}. The
+ password corresponding to the alias name is stored in an encrypted
+ form. The update-password-alias subcommand takes both a secure
+ interactive form (in which the user is prompted for all information)
+ and a more script-friendly form, in which the password is propagated on
+ the command line.
+
+ This subcommand is supported in remote mode only.
+
+OPTIONS
+ --help, -?
+ Displays the help text for the subcommand.
+
+OPERANDS
+ aliasname
+ This is the name of the password as it appears in domain.xml.
+
+EXAMPLES
+ Example 1, Updating a Password Alias
+
+ asadmin> update-password-alias jmspassword-alias
+ Please enter the alias password>
+ Please enter the alias password again>
+ Command update-password-alias executed successfully.
+
+EXIT STATUS
+ 0
+ command executed successfully
+
+ 1
+ error in executing the command
+
+SEE ALSO
+ delete-password-alias(1), list-password-aliases(1),
+ create-password-alias(1)
+
+ asadmin(1M)
+
+Java EE 8 09 Aug 2017 update-password-alias(1)
diff --git a/nucleus/security/core/src/main/resources/com/sun/enterprise/security/admin/cli/LocalStrings.properties b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/admin/cli/LocalStrings.properties
new file mode 100644
index 0000000..e5c48ec
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/admin/cli/LocalStrings.properties
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+
+enable.secure.admin.command=Enable domain-wide secure administration
+enable.secure.admin.errenable=Error enabling secure admin
+disable.secure.admin.command=Disable domain-wide secure administration
+disable.secure.admin.errdisable=Error disabling secure admin
+enable.secure.admin.badAlias=Error enabling secure admin; the keystore does not contain the specified {0,choice,1#alias|1<aliases} {1}
+
+noKeyStore=Could not access key store
+noAlias=Could not find the alias {0} in the key store
+certNotX509Certificate=Certificate in the key store with alias {0} is not an X509 certificate, as expected
+errVal=Error validating username and password alias
+notAdminUser=The username {0} is not a valid admin user
+adminsWithEmptyPW=At least one admin user has an empty password, which secure admin does not permit. Use the change-admin-password command or the admin console to create non-empty passwords for admin accounts.
+restartReq=You must restart all running servers for the change in secure admin to take effect.
diff --git a/nucleus/security/core/src/main/resources/com/sun/enterprise/security/audit/LocalStrings.properties b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/audit/LocalStrings.properties
new file mode 100644
index 0000000..2fc941b
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/audit/LocalStrings.properties
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+auditmgr.admininvocation=Audit: Audit Module {0} threw the following exception during admin invocation :
+auditmgr.authentication=Audit: Audit Module {0} threw the following exception during authentication:
+auditmgr.logout=Audit: Audit Module {0} threw the following exception during logout:
+auditmgr.loaderror=Audit: Cannot load AuditModule = {0}
+auditmgr.badinit=Audit: Cannot load Audit Module Initialization information. AuditModules will not be loaded.
+auditmgr.serverStartup=Audit: Audit Module {0} threw the following exception during server startup :
+auditmgr.serverShutdown=Audit: Audit Module {0} threw the following exception during server shutdown :
diff --git a/nucleus/security/core/src/main/resources/com/sun/enterprise/security/cli/.gitkeep_empty_dir b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/cli/.gitkeep_empty_dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/com/sun/enterprise/security/cli/.gitkeep_empty_dir
diff --git a/nucleus/security/core/src/main/resources/com/sun/logging/enterprise/system/core/security/LogStrings.properties b/nucleus/security/core/src/main/resources/com/sun/logging/enterprise/system/core/security/LogStrings.properties
new file mode 100644
index 0000000..28ca946
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/com/sun/logging/enterprise/system/core/security/LogStrings.properties
@@ -0,0 +1,238 @@
+#
+# Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+# Common iAS security messages.
+security.exception=SEC1000: Caught exception.
+security.secmgron=SEC1001: Security Manager is ON.
+security.secmgroff=SEC1002: Security Manager is OFF.
+security.secmgr.could.not.override=SEC1003: Could not override SecurityManager.
+
+#Security Service messages
+sec.service.startup.enter=SEC1010: Entering Security Startup Service
+sec.service.startup.exit=SEC1011: Security Service(s) Started Successfully
+
+# General login processing messages: start 1050
+certlogin.badrealm=SEC1050: Certificate authentication requires certificate realm. Check server configuration.
+
+
+# Realms and Login Modules: start at 1100
+
+realmconfig.disable=SEC1100: Disabled realm [{0}] due to errors.
+realmconfig.nogood=SEC1101: No realms available. Authentication services disabled.
+realmconfig.noctx=SEC1102: Incomplete configuration, login module not specified.
+iasrealm.noauth=SEC1103: No AuthenticationHandler available for this realm.
+passwordlm.nocreds=SEC1104: Error while obtaining private subject credentials.
+passwordlm.nopwdcred=SEC1105: A PasswordCredential was required but not provided.
+ldaprealm.searcherror=SEC1106: Error during LDAP search with filter [{0}].
+filerealm.readerror=SEC1109: Error reading file realm data.
+certrealm.nojaas=SEC1110: JAAS context requested from certificate realm. Configuration error is likely.
+jdbcrealm.grouperror=SEC1111: Cannot load group for JDBC realm user [{0}].
+jdbcrealm.invaliduser=SEC1112: Cannot validate user [{0}] for JDBC realm.
+ldaprealm.exception=SEC1113: Exception in LdapRealm when trying to authenticate user.
+ldaprealm.groupsearcherror=SEC1114: Exception in LdapRealm when trying to locate groups for user.
+realm.loaded.successfully=SEC1115: Realm [{0}] of classtype [{1}] successfully created.
+realm.updated.successfully=SEC1117: Realm [{0}] successfully updated.
+ldaprealm.pwd.dealiasing.failed=SEC1118: Error while de-aliasing the aliased password
+
+# Audit: start at 1120
+audit.badinit=SEC1120: Error reading audit configuration.
+audit.enabled=SEC1122: Audit enabled.
+audit.string_private_audit=SEC1123: Audit: principal=
+# Note- these are partial strings, no message code.
+audit.denied= DENIED
+audit.ok= OK
+audit.methodname= method=
+audit.session= session=
+
+# Programmatic Login: start at 1130
+proglogin.noperm=SEC1130: Code does not have permission to invoke programmatic login mechanism.
+prologout.noperm=SEC1131: Code does not have permission to invoke programmatic logout mechanism.
+
+# JACC and policy: start at 1140
+policy.propoverride=SEC1140: Policy provider configuration overridden by property {0} with value {1}
+policy.nosuchname=SEC1141: Requested jacc-provider [{0}] is not configured in domain.xml.
+policy.errorreading=SEC1142: Error while reading policy-provider in domain.xml.
+policy.loading=SEC1143: Loading policy provider {0}.
+policy.installerror=SEC1144: Error while installing policy provider:
+policy.notloading=SEC1145: No policy provider defined. Will use the default JDK Policy implementation.
+policy.factoryoverride=SEC1146: Policy configuration factory overridden by property {0} with value {1}
+policy.nofactory=SEC1147: Policy configuration factory not defined.
+policy.configure=SEC1148: Cannot load policy file for Application.
+# JMAC: start at 1200 : The JASPIC Provider Framework has some of these, need to cleanup
+jmac.unexpandedproperty=SEC1200: Unable to expand provider property value, unexpanded value passed to provider.
+jmac.loginfail=SEC1201: Login failed for user: {0}
+jmac.unsupportreadprinciple=SEC1202: No support to read Principals in SecretKeyCallback.
+jmac.factory_unable_to_load_provider=SEC1203: GFAuthConfigFactory unable to load Provider: {0}, reason: {1}
+jmac.factory_auth_config_loader_failure=SEC1204: GFAuthConfigFactory loader failure.
+jmac.factory_cannot_write_file=SEC1205: Cannot write to file {0}. Updated provider list will not be persisted.
+jmac.factory_could_not_persist=SEC1206: Could not persist updated provider list due to {0}, Will use default providers when reloaded.
+jmac.factory_could_not_read=SEC1207: Could not read auth configuration file due to {0} Will use default providers.
+jmac.factory_file_not_found=SEC1208: Configuration file does not exist at {0}. Will use default providers.
+
+# WS Security: start at 2000
+ws.error_validate_request=SEC2002: Container-auth: wss: Error validating request
+ws.error_secure_response=SEC2003: Container-auth: wss: Error securing response
+ws.error_secure_request=SEC2004: Container-auth: wss: Error securing request
+ws.error_validate_response=SEC2005: Container-auth: wss: Error validating response
+ws.error_not_soap=SEC2006: Container-auth: wss: Not a SOAP message context.
+
+# Existing RI: start at 5001
+java_security.unknown_credential=SEC5019:ERROR: Unknown credential provided. Class: [{0}]
+java_security.anonymous_role_reading_exception=SEC5022: Error reading anonymous role.
+java_security.gen_security_context=SEC5026: Exception generating security context
+java_security.KeyStore_load_exception=SEC5028: Exception loading keystore
+java_security.KeyStore_store_exception=SEC5029: Exception storing keystore
+java_security.provider_exception=SEC5030: Exception loading security provider
+java_security.getName_exception=SEC5031: Exception getting security provider name
+java_security.main_exception=SEC5032: Security main exception
+java_security.security_context_exception=SEC5036: Exception in getting security context
+java_security.default_user_login_Exception=SEC5038: Default user login exception.
+java_security.name_password_entry_exception=SEC5039: Exception entering name and password for security
+java_security.accesscontroller_action_exception=SEC5043: Exception in security accesscontroller action
+java_security.audit_auth_refused=SEC5046: Audit: Authentication refused for [{0}].
+java_security.security_context_permission_exception=SEC5048: doAsPrivileged AuthPermission required to set SecurityContext.
+java_security.security_context_unexpected_exception=SEC5049: Unexpected exception while attempting to set SecurityContext.
+java_security.security_context_nochange=SEC5050: Current Context unchanged.
+java_security.null_subject=SEC5052: null Subject used in SecurityContext construction.
+java_security.role_mapping_conflict=SEC5055: Role mapping conflicts found in application {0}. Some roles may not be mapped.
+
+java_security.init_securitylifecycle_fail=SEC5101: Fail to instantiate the SecurityLifecycle.
+
+
+# EE specific: start at 8001
+
+#ACC specific: start at 9001
+main.jmac_default_factory=SEC9001: ACC: Error in initializing JSR 196 Default Factory
+acc.secmgron=SEC9002: ACC: Security Manager is ON
+acc.secmgroff=SEC9003: ACC: Security Manager is OFF
+
+#programmatic login specific
+prog.login.failed=SEC9050: Programmatic login failed
+prog.logout.failed=SEC9051: Programmatic logout failed
+
+#ejb.security log messages
+iiop.createcontextsec_exception=IIOP1000: Exception creating ASContext
+iiop.user_password_exception=IIOP1001: Exception getting username and password
+iiop.principal_error=IIOP1002: Principal propagation: Cannot find principal information in subject
+iiop.credential_error=IIOP1003: Principal propagation: Cannot find credential information in subject.
+iiop.cannot_find_keyalias=IIOP1004: Key alias {0} not found in keystore
+iiop.Exception=IIOP1005: An exception has occured in the ejb security initialization.
+
+
+#Diagnostic messages for security/core
+
+SEC1105.diag.cause.1=PasswordCredential was required, but not supplied.
+SEC1105.diag.check.1=Please check if the password is provided
+SEC1104.diag.cause.1=Private Credentials of Subject not available
+SEC1104.diag.check.1=Please check if the private credentials are available
+SEC5028.diag.cause.1=There was an exception while loading keystore
+SEC5028.diag.check.1=Please check the if the file path and password are correct
+SEC5029.diag.cause.1=There was an exception while storing the keystore
+SEC5029.diag.check.1=Please check the if the file path and password are correct
+SEC5030.diag.cause.1=There was an exception while loading the security provider
+SEC5030.diag.check.1=Please check the if the Provider classname is correct.
+SEC5031.diag.cause.1=There was an exception while obtaining the name of the Provider.
+SEC5031.diag.check.1=Please check the if the Provider name is correct.
+SEC1114.diag.cause.1=There was an exception while installing the Policy Provider.
+SEC1114.diag.check.1=Please check the if the Policy Provider is correct
+SEC1118.diag.cause.1=There was an exception while de-aliasing the aliased password provided as the ldaprealm property.
+SEC1118.diag.check.1=Please check the if the alias and the password configured are correct
+SEC1146.diag.cause.1=Policy Configuration Factory overridden
+SEC1146.diag.check.1=Please check if the system property javax.security.jacc.PolicyConfigurationFactory.provider has not been set.
+SEC1147.diag.cause.1=Policy Configuration Factory not defined
+SEC1147.diag.check.1=Please check if the Policy Configuration Factory has been defined.
+SEC1145.diag.cause.1=No policy provider defined. Will use the default JDK Policy implementation.
+SEC1145.diag.check.1=No policy provider defined. Will use the default JDK Policy implementation.
+SEC1142.diag.cause.1=Error while reading policy-provider in domain.xml.
+SEC1142.diag.check.1=Please check if the policy provider defined is correct.
+SEC1140.diag.cause.1=Policy Provider Configuration Property is overridden by property javax.security.jacc.auth.policy.provider.
+SEC1140.diag.check.1=Policy Provider Configuration Property is overridden by property javax.security.jacc.auth.policy.provider.
+SEC1141.diag.cause.1=JaccProvider class not found for name defined.
+SEC1141.diag.check.1=Please check if the name of the Jacc provider is defined correctly.
+SEC5038.diag.cause.1=There was an exception while authenticating the default caller principal
+SEC5038.diag.check.1=There was an exception while authenticating the default caller principal
+SEC5036.diag.cause.1=There was an exception obtaining the default security context.
+SEC5036.diag.check.1=There was an exception obtaining the default security context.
+SEC5048.diag.cause.1=AuthPermission required to set SecurityContext,
+SEC5048.diag.check.1=AuthPermission required to set SecurityContext,
+SEC5049.diag.cause.1=There was an unexpected exception while setting the security context
+SEC5049.diag.check.1=There was an unexpected exception while setting the security context
+SEC5039.diag.cause.1=An exception occurred while processing username and password for security
+SEC5039.diag.check.1=An exception occurred while processing username and password for security
+SEC5055.diag.cause.1=Principal-Group-Role Mapping conflicts in the application
+SEC5055.diag.check.1=Please check if the roles have been mapped to the same principals/groups consistently in all the descriptors.
+SEC1103.diag.cause.1=The Realm configured is not an instance of CertificateRealm, Certificate authentication requires certificate realm.
+SEC1103.diag.check.1=Please check if the realm class is an instance of CertificateRealm
+SEC1112.diag.cause.1=Cannot obtain the password for the user provided.
+SEC1112.diag.check.1=Please check the JDBC configuration, encoding algorithm and the password for the user.
+SEC1111.diag.cause.1=Exception while obtaining groups for the users.
+SEC1111.diag.check.1=Please check the JDBC configuration, encoding algorithm and the groups for the user.
+SEC5043.diag.cause.1=Exception while extracting username and realm from the subject post login
+SEC5043.diag.check.1=Exception while extracting username and realm from the subject post login
+SEC1130.diag.cause.1=Code does not have permission to invoke programmatic login mechanism.
+SEC1130.diag.check.1=Code does not have permission to invoke programmatic login mechanism.
+SEC1103.diag.cause.1=No AuthenticationHandler available for this realm.
+SEC1103.diag.check.1=Check of the Realm has been configured correctly. This is the base class method that has to be overridden
+SEC1110.diag.cause.1=JAAS context requested from certificate realm.
+SEC1110.diag.check.1=Certificate Realm does not have a JAAS context. Please check the configuration
+SEC1109.diag.cause.1=Error reading keyfile of filerealm
+SEC1109.diag.check.1=Please check if the keyfile for the filerealm is configured correctly and is in place.
+SEC1000.diag.cause.1=A Security Exception has been thrown
+SEC1000.diag.check.1=A Security Exception has been thrown
+SEC1106.diag.cause.1=Error during LDAP search
+SEC1106.diag.check.1=Please check the LDAP configuration
+SEC1102.diag.cause.1=Error during SolarisRealm initialization. LoginModule not specified
+SEC1102.diag.check.1=Please provide the jaas-context in the SolarisRealm configuration
+SEC1203.diag.cause.1=Error while loading ConfigProvider.
+SEC1203.diag.check.1=Please check if the configprovider has been configured correctly.
+SEC1204.diag.cause.1=Error while loading the persisted entries of GFAuthConfigFactory
+SEC1204.diag.check.1=Error while loading the persisted entries of GFAuthConfigFactory
+SEC1207.diag.cause.1=Could not read auth configuration file. The default provider will be used.
+SEC1207.diag.check.1=Could not read auth configuration file. The default provider will be used.
+SEC1206.diag.cause.1=Could not persist updated provider list due to {0}. Will use default providers when reloaded.
+SEC1206.diag.check.1=Could not persist updated provider list due to {0}. Will use default providers when reloaded.
+SEC1205.diag.cause.1=Cannot write to file. Updated provider list will not be persisted.
+SEC1205.diag.check.1=Cannot write to file. Updated provider list will not be persisted.
+SEC1003.diag.cause.1=Could not override SecurityManager.
+SEC1003.diag.check.1=Could not override SecurityManager.
+SEC9001.diag.cause.1=GFAuthConfigFactory not in classpath or not enough permissions to call Security.setProperty
+SEC9001.diag.check.1=Please check if appclient classpath has GFAuthConfigFactory class and ensure required permissions are given.
+SEC1114.diag.cause.1=Invalid user or improper LDAPRealm configuration
+SEC1114.diag.check.1=Check the LDAPRealm Configuration in GlassFish.
+
+SEC9050.diag.cause.1=Check the exception stack-trace for more details
+SEC9050.diag.check.1=Check if the credential username/password/certificate was a valid one
+SEC9051.diag.cause.1=Check the exception stack-trace for more details
+SEC9051.diag.check.1=Check the exception stack-trace, could be an internal server error or a bug.
+
+
+#ejb.security Diagnostic messages
+
+IIOP1000.diag.cause.1=An error occured while creating the ASContext or SASContext
+IIOP1000.diag.check.1=Please check the values provided in the descriptor for the IOR security config
+IIOP1001.diag.cause.1=An exception occured while obtaining the username and password
+IIOP1001.diag.check.1=Please check the username and password provided
+IIOP1002.diag.cause.1=The principal information is not found in the subject
+IIOP1002.diag.check.1=Please check the config settings for identity propagation
+IIOP1003.diag.cause.1=Credential information is not found in the subject
+IIOP1003.diag.check.1=Please check the config settings for identity propogation
+IIOP1004.diag.cause.1=Alias key is not found in the keystore
+IIOP1004.diag.check.1=Please check the if the name of the alias is right and of the keystore contains the key of the alias
+IIOP1005.diag.cause.1=An Exception has occured in the ejb security initialization
+IIOP1005.diag.check.1=Please check the if the IOR security configuration of the ejb is correct
+
+
diff --git a/nucleus/security/core/src/main/resources/config/admin-keyfile b/nucleus/security/core/src/main/resources/config/admin-keyfile
new file mode 100644
index 0000000..785d8c5
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/admin-keyfile
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+
+anonymous;{SSHA}w9WBMj/jphXlgDWPgozFSSzUgy5Fd/ONd7nPtw==;asadmin
+
+# Domain User and Password - Do Not Delete Entry Above
diff --git a/nucleus/security/core/src/main/resources/config/cacerts.jks b/nucleus/security/core/src/main/resources/config/cacerts.jks
new file mode 100644
index 0000000..5349943
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/cacerts.jks
Binary files differ
diff --git a/nucleus/security/core/src/main/resources/config/javaee.server.policy b/nucleus/security/core/src/main/resources/config/javaee.server.policy
new file mode 100644
index 0000000..5834a07
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/javaee.server.policy
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// App-client EE permissions
+grant codebase "file:/module/Car" {
+
+ permission java.awt.AWTPermission "accessClipboard";
+ permission java.awt.AWTPermission "accessEventQueue";
+ permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
+
+ permission java.lang.RuntimePermission "loadLibrary.*";
+ permission java.lang.RuntimePermission "exitVM";
+ permission java.lang.RuntimePermission "queuePrintJob";
+
+ permission java.net.SocketPermission "*", "connect";
+ permission java.net.SocketPermission "localhost:1024-", "accept,listen";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write";
+ permission java.util.PropertyPermission "*", "read";
+
+};
+
+// Applet-client EE permissions
+grant codebase "file:/module/Applet-Client" {
+
+ permission java.net.SocketPermission "*", "connect";
+ permission java.util.PropertyPermission "*", "read";
+
+};
+
+
+// EJB EE permissions
+grant codebase "file:/module/Ejb" {
+ permission java.lang.RuntimePermission "loadLibrary";
+ permission java.lang.RuntimePermission "queuePrintJob";
+ permission java.net.SocketPermission "*", "connect";
+ permission java.io.FilePermission "*", "read,write";
+ permission java.util.PropertyPermission "*", "read";
+};
+
+
+// Web EE permissions
+grant codebase "file:/module/Web" {
+ permission java.lang.RuntimePermission "loadLibrary";
+ permission java.lang.RuntimePermission "queuePrintJob";
+ permission java.net.SocketPermission "*", "connect";
+ permission java.io.FilePermission "*", "read,write";
+ permission java.io.FilePermission "SERVLET-CONTEXT-TEMPDIR", "read,write";
+ permission java.util.PropertyPermission "*", "read";
+};
+
+// Resource adapter EE permissions
+grant codebase "file:/module/Rar" {
+ permission java.lang.RuntimePermission "loadLibrary";
+ permission java.lang.RuntimePermission "queuePrintJob";
+ permission java.net.SocketPermission "*", "connect";
+ permission java.io.FilePermission "*", "read,write";
+ permission java.util.PropertyPermission "*", "read";
+};
diff --git a/nucleus/security/core/src/main/resources/config/keyfile b/nucleus/security/core/src/main/resources/config/keyfile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/keyfile
diff --git a/nucleus/security/core/src/main/resources/config/keystore.jks b/nucleus/security/core/src/main/resources/config/keystore.jks
new file mode 100644
index 0000000..33a95a0
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/keystore.jks
Binary files differ
diff --git a/nucleus/security/core/src/main/resources/config/login.conf b/nucleus/security/core/src/main/resources/config/login.conf
new file mode 100644
index 0000000..c81d5ba
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/login.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+fileRealm {
+ com.sun.enterprise.security.auth.login.FileLoginModule required;
+};
+
+ldapRealm {
+ com.sun.enterprise.security.auth.login.LDAPLoginModule required;
+};
+
+solarisRealm {
+ com.sun.enterprise.security.auth.login.SolarisLoginModule required;
+};
+
+jdbcRealm {
+ com.sun.enterprise.security.ee.auth.login.JDBCLoginModule required;
+};
+jdbcDigestRealm {
+ com.sun.enterprise.security.ee.auth.login.JDBCDigestLoginModule required;
+};
+pamRealm {
+ com.sun.enterprise.security.auth.login.PamLoginModule required;
+};
+
diff --git a/nucleus/security/core/src/main/resources/config/restrict.server.policy b/nucleus/security/core/src/main/resources/config/restrict.server.policy
new file mode 100644
index 0000000..6d103f4
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/restrict.server.policy
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// EJB default restricted permissions
+grant codebase "file:/module/Ejb" {
+ //following restricts the use of 'java.security.AllPermission' in permissions.xml
+ permission com.sun.enterprise.security.perms.VoidPermission;
+};
+
+// Web App default restricted permissions
+grant codebase "file:/module/Web" {
+ //following restricts the use of 'java.security.AllPermission' in permissions.xml
+ permission com.sun.enterprise.security.perms.VoidPermission;
+};
+
+// Connector default restricted permissions
+grant codebase "file:/module/Rar" {
+ //following restricts the use of 'java.security.AllPermission' in permissions.xml
+ permission com.sun.enterprise.security.perms.VoidPermission;
+};
+
+
+// App client default restricted permissions
+grant codebase "file:/module/Car" {
+ //following restricts the use of 'java.security.AllPermission' in permissions.xml
+ permission com.sun.enterprise.security.perms.VoidPermission;
+};
+
+
diff --git a/nucleus/security/core/src/main/resources/config/server.policy b/nucleus/security/core/src/main/resources/config/server.policy
new file mode 100644
index 0000000..4bceff9
--- /dev/null
+++ b/nucleus/security/core/src/main/resources/config/server.policy
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+// classes in lib get all permissions by default
+grant codeBase "file:${com.sun.aas.installRoot}/lib/-" {
+ permission java.security.AllPermission;
+};
+
+// Core server classes get all permissions by default
+grant codeBase "file:${com.sun.aas.installRoot}/modules/-" {
+ permission java.security.AllPermission;
+};
+
+// Felix classes get all permissions by default
+grant codeBase "file:${com.sun.aas.installRoot}/osgi/felix/bin/-" {
+ permission java.security.AllPermission;
+};
+
+// iMQ classes get all permissions by default
+grant codeBase "file:${com.sun.aas.imqLib}/-" {
+ permission java.security.AllPermission;
+};
+
+// Derby driver classes get all permissions by default
+grant codeBase "file:${com.sun.aas.derbyRoot}/lib/-" {
+ permission java.lang.RuntimePermission "createClassLoader";
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write";
+};
+
+
+// permission for JDK's tools.jar to enable webservice annotation processing
+// at runtime by wsgen tool:
+// permission java.lang.RuntimePermission "createClassLoader";
+//
+// permission for JDK's tools.jar to sign JARs at runtime for
+// Java Web Start support:
+// permissions java.security.AllPermission;
+// on the advice of the JDK tools folks. Should be refined later.
+//Bug Glassfish-21012 - changing to the right location of tools.jar
+grant codeBase "file:${com.sun.aas.javaRoot}/../lib/tools.jar" {
+ permission java.security.AllPermission;
+};
+
+//Loading MBeans from anywhere, to take care of side effects of 6235678.
+grant {
+ permission javax.management.MBeanTrustPermission "register" ;
+};
+//Loading MBeans from anywhere, to take care of side effects of 6235678.
+
+
+// Basic set of required permissions granted to all remaining code
+// The permission FilePermission "<<ALL FILES>>", "read,write"
+// allows all applications to read and write any file in the filesystem.
+// It should be changed based on real deployment needs. If you know your
+// applications just need to read/write a few directories consider removing
+// this permission and adding grants indicating those specific directories.
+// against the codebase of your application(s).
+grant {
+ //Workaround for bugs #6484935, 6513799
+ permission java.lang.RuntimePermission "getProtectionDomain";
+ permission com.sun.corba.ee.impl.presentation.rmi.DynamicAccessPermission "access";
+ permission java.util.PropertyPermission "*", "read,write";
+
+ permission java.lang.RuntimePermission "loadLibrary.*";
+ permission java.lang.RuntimePermission "queuePrintJob";
+ permission java.net.SocketPermission "*", "connect";
+
+ // work-around for pointbase bug 4864405
+ permission java.io.FilePermission "${com.sun.aas.instanceRoot}${/}lib${/}databases${/}-", "delete";
+ permission java.io.FilePermission "${java.io.tmpdir}${/}-", "delete";
+
+ permission java.util.PropertyPermission "*", "read";
+
+ permission java.lang.RuntimePermission "modifyThreadGroup";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "setContextClassLoader";
+ permission javax.management.MBeanPermission "[com.sun.messaging.jms.*:*]", "*";
+
+ // Following needed for CTS to pass with SM on, bug 16344201
+ permission java.lang.RuntimePermission "closeClassLoader";
+ permission java.io.SerializablePermission "enableSubstitution";
+ permission java.security.SecurityPermission "getProperty.package.definition";
+
+};
+
+
+// Following grant block is only required by Connectors. If Connectors
+// are not in use the recommendation is to remove this grant.
+grant {
+ permission javax.security.auth.PrivateCredentialPermission "javax.resource.spi.security.PasswordCredential * \"*\"","read";
+};
+
+// Following grant block is only required for Reflection. If Reflection
+// is not in use the recommendation is to remove this section.
+grant {
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+};
+
+// Permissions to invoke CORBA objects in server
+grant {
+ permission com.sun.enterprise.security.CORBAObjectPermission "*", "*";
+};
+
+ // GLASSFISH-21011
+grant {
+ permission java.io.SerializablePermission "enableSubclassImplementation";
+};
+
+grant codeBase "file:${com.sun.aas.instanceRoot}/applications/-"{
+ permission java.io.FilePermission "<<ALL FILES>>", "read,write";
+};
diff --git a/nucleus/security/pom.xml b/nucleus/security/pom.xml
new file mode 100644
index 0000000..00ffac6
--- /dev/null
+++ b/nucleus/security/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.main</groupId>
+ <artifactId>glassfish-nucleus-parent</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ </parent>
+ <groupId>org.glassfish.main.security</groupId>
+ <artifactId>nucleus-security</artifactId>
+ <packaging>pom</packaging>
+ <name>Nucleus Security Parent</name>
+ <description>Security Infrastructure and Technology Integration Modules</description>
+ <modules>
+ <module>core</module>
+ <module>ssl-impl</module>
+ <module>services</module>
+ </modules>
+</project>
diff --git a/nucleus/security/services/osgi.bundle b/nucleus/security/services/osgi.bundle
new file mode 100644
index 0000000..4c88d91
--- /dev/null
+++ b/nucleus/security/services/osgi.bundle
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+-exportcontents: \
+ org.glassfish.security.services.api; \
+ org.glassfish.security.services.api.authentication; \
+ org.glassfish.security.services.api.authorization; \
+ org.glassfish.security.services.api.common; \
+ org.glassfish.security.services.api.context; \
+ org.glassfish.security.services.spi; \
+ org.glassfish.security.services.spi.authentication; \
+ org.glassfish.security.services.spi.authorization; \
+ org.glassfish.security.services.common; \
+ org.glassfish.security.services.commands; \
+ org.glassfish.security.services.impl; \
+ org.glassfish.security.services.impl.common; \
+ org.glassfish.security.services.impl.authorization; \
+ org.glassfish.security.services.provider.authorization; \
+ org.glassfish.security.services.config; version=${project.osgi.version}
diff --git a/nucleus/security/services/pom.xml b/nucleus/security/services/pom.xml
new file mode 100644
index 0000000..9a9030c
--- /dev/null
+++ b/nucleus/security/services/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.glassfish.main.security</groupId>
+ <artifactId>nucleus-security</artifactId>
+ <version>5.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>security-services</artifactId>
+ <packaging>glassfish-jar</packaging>
+
+ <name>Security Services and SPI</name>
+
+ <build>
+ <plugins>
+ <!-- JDK 8u171+, PasswordAliasTest fails due to serialization issue
+ Using forked process helps the tests to pass -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkMode>always</forkMode>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-junitrunner</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.admin</groupId>
+ <artifactId>config-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>common-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>internal-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>glassfish-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.security</groupId>
+ <artifactId>security</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.annotations</groupId>
+ <artifactId>logging-annotation-processor</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/SecurityService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/SecurityService.java
new file mode 100644
index 0000000..7b409eb
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/SecurityService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api;
+
+import org.glassfish.security.services.config.SecurityConfiguration;
+
+/**
+ * Base interface used by all security services.
+ */
+public interface SecurityService {
+ /**
+ * Initialize the security service instance with the specific security service configuration.
+ */
+ public void initialize(SecurityConfiguration securityServiceConfiguration);
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AbstractInternalSystemAdministrator.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AbstractInternalSystemAdministrator.java
new file mode 100644
index 0000000..ff0b1df
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AbstractInternalSystemAdministrator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authentication;
+
+import javax.inject.Inject;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.internal.api.InternalSystemAdministrator;
+
+/**
+ * Implements most of the internal system administrator.
+ * <p>
+ * Different concrete subclasses implement {@link #getAdminGroupName() }
+ * and {@link #getInternalUsername() } and {@link #createSubject() } differently.
+ *
+ * @author tjquinn
+ */
+public abstract class AbstractInternalSystemAdministrator implements InternalSystemAdministrator, PostConstruct {
+
+ private Subject subject;
+
+ @Inject
+ private AuthenticationService authService;
+
+ @Override
+ public void postConstruct() {
+ subject = createSubject();
+ }
+
+ @Override
+ public Subject getSubject() {
+ return subject;
+ }
+
+ /**
+ * Creates a subject using the impersonate method on the authentication
+ * service.
+ *
+ * @return the Subject to use for the internal system administrator.
+ */
+ protected Subject createSubject() {
+ Subject s;
+ try {
+ s = authService.impersonate(
+ getInternalUsername(),
+ new String[] {getAdminGroupName()},
+ null /* no pre-existing subject */,
+ true /* isVirtual */);
+ return s;
+ } catch (LoginException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ abstract protected String getInternalUsername();
+
+ abstract protected String getAdminGroupName();
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AuthenticationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AuthenticationService.java
new file mode 100644
index 0000000..cd4dd9e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/AuthenticationService.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authentication;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.jvnet.hk2.annotations.Contract;
+
+import org.glassfish.security.services.api.SecurityService;
+
+/**
+ * The AuthenticationService provides basic authentication functions.
+ * Consumers of the service must establish Subjects in any security context.
+ */
+@Contract
+public interface AuthenticationService extends SecurityService {
+ /**
+ * Log in a user with username and password.
+ *
+ * @param username The username.
+ * @param password The password.
+ * @param subject An optional Subject to receive principals and credentials for the logged in user.
+ * If provided, it will be returned as the return value; if not, a new Subject will be returned.
+ *
+ * @return A Subject representing the logged in user.
+ *
+ * @throws LoginException
+ */
+ public Subject login(String username, char[] password, Subject subject)
+ throws LoginException;
+
+ /**
+ * Authenticate using a CallbackHandler to provider username/password, X.509 certificate, or
+ * Secure Admin token.
+ *
+ * @param cbh The CallbackHandler.
+ * @param subject An optional Subject to receive principals and credentials for the logged in user.
+ * If provided, it will be returned as the return value; if not, a new Subject will be returned.
+ *
+ * @return A Subject representing the logged in user.
+ *
+ * @throws LoginException
+ */
+ public Subject login(CallbackHandler cbh, Subject subject) throws LoginException;
+
+ /**
+ * Impersonate a user, specifying the user and group principal names that
+ * should be established in the resulting Subject.
+ *
+ * Note that, that this method always behaves as if <bold>virtual</bold> were true in the case
+ * that the underlying user store provider does not support user lookup.
+ *
+ * @param user The username.
+ * @param groups An array of group names. If <bold>virtual</bold> is true, group principals will be created
+ * using this array. If <bold>virtual</bold> is false and groups is non-null, it will be used to filter the
+ * groups returned by the configured UserStoreProvider.
+ * @param subject An optional Subject to receive principals and credentials for the logged in user.
+ * If provided, it will be returned as the return value; if not, a new Subject will be returned.
+ * @param virtual If true, simply create a subject with the given user and group names. If false, configured
+ * UserStoreProvider will be queried for the given username and a Subject created only if the user exists. Groups
+ * will be populated with the intersection of the groups parameter and the groups returned by the UserStoreProvider.
+ *
+ * @return A Subject representing the impersonated user.
+ *
+ * @throws LoginException
+ */
+ public Subject impersonate(String user, String[] groups, Subject subject, boolean virtual)
+ throws LoginException;
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/ImpersonationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/ImpersonationService.java
new file mode 100644
index 0000000..6625d93
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authentication/ImpersonationService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authentication;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * The Impersonation Service
+ */
+@Contract
+public interface ImpersonationService {
+ /**
+ * Impersonate a user, specifying the user and group principal names that
+ * should be established in the resulting Subject.
+ *
+ * Note that, that this method always behaves as if <bold>virtual</bold> were true in the case
+ * that the underlying user store provider does not support user lookup.
+ *
+ * @param user The username.
+ * @param groups An array of group names. If <bold>virtual</bold> is true, group principals will be created
+ * using this array. If <bold>virtual</bold> is false and groups is non-null, it will be used to filter the
+ * groups returned by the configured UserStoreProvider.
+ * @param subject An optional Subject to receive principals and credentials for the logged in user.
+ * If provided, it will be returned as the return value; if not, a new Subject will be returned.
+ * @param virtual If true, simply create a subject with the given user and group names. If false, configured
+ * UserStoreProvider will be queried for the given username and a Subject created only if the user exists. Groups
+ * will be populated with the intersection of the groups parameter and the groups returned by the UserStoreProvider.
+ *
+ * @return A Subject representing the impersonated user.
+ *
+ * @throws LoginException
+ */
+ public Subject impersonate(String user, String[] groups, Subject subject, boolean virtual)
+ throws LoginException;
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationAdminConstants.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationAdminConstants.java
new file mode 100644
index 0000000..1e21993
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationAdminConstants.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Common attribute names, used in authorization and set by code using
+ * the authorization service.
+ *
+ * @author tjquinn
+ */
+public interface AuthorizationAdminConstants {
+ public final static String ISDAS_ATTRIBUTE = "isDAS";
+
+ public final static String ADMIN_TOKEN = "adminToken";
+ public final static String REST_TOKEN = "restToken";
+ public final static String LOCAL_PASSWORD = "localPassword";
+ public final static String SERVER = "server";
+
+ /*
+ * The presence of either of these attributes means the associated
+ * subject is not linked to a specific admin user but was authenticated
+ * as trustworthy in some other way.
+ */
+ public final static Set<String> TRUSTED_FOR_DAS_OR_INSTANCE =
+ Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(LOCAL_PASSWORD, SERVER)));
+
+ public final static String ADMIN_GROUP = "asadmin"; // must match with value in admin/util module's AdminConstants class
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationService.java
new file mode 100755
index 0000000..2feb85a
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AuthorizationService.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import java.net.URI;
+import java.security.Permission;
+import java.util.List;
+import javax.security.auth.Subject;
+
+import org.glassfish.security.services.api.SecurityService;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * The <code>AuthorizationService</code> interface provides methods that allow server and container
+ * to determine whether access should be allowed to a particular resource. It is intended for
+ * internal use, not for use by applications.
+ */
+@Contract
+public interface AuthorizationService extends SecurityService {
+
+ /**
+ * Determines whether the given Subject has been granted the specified Permission
+ * by delegating to the configured java.security.Policy object. This method is
+ * a high-level convenience method that tests for a Subject-based permission
+ * grant without reference to the AccessControlContext of the caller.
+ *
+ * In addition, this method isolates the query from the underlying Policy configuration
+ * model. It could, for example, multiplex queries across multiple instances of Policy
+ * configured in an implementation-specific way such that different threads, or different
+ * applications, query different Policy objects. The initial implementation simply
+ * delegates to the configured Policy as defined by Java SE.
+ *
+ * @param subject The Subject for which permission is being tested.
+ * @param permission The Permission being queried.
+ * @return True or false, depending on whether the specified Permission
+ * is granted to the Subject by the configured Policy.
+ * @throws IllegalArgumentException Given null or illegal subject or permission
+ */
+ public boolean isPermissionGranted(Subject subject, Permission permission);
+
+ /**
+ * Determines whether the given Subject is authorized to access the given resource,
+ * specified by a URI.
+ *
+ * @param subject The Subject being tested.
+ * @param resource URI of the resource being tested.
+ * @return True or false, depending on whether the access is authorized.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ */
+ public boolean isAuthorized(Subject subject, URI resource);
+
+ /**
+ * Determines whether the given Subject is authorized to access the given resource,
+ * specified by a URI.
+ *
+ * @param subject The Subject being tested.
+ * @param resource URI of the resource being tested.
+ * @param action The action, with respect to the resource parameter,
+ * for which authorization is desired. To check authorization for all actions,
+ * action is represented by null or "*".
+ * @return True or false, depending on whether the access is authorized.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ */
+ public boolean isAuthorized(Subject subject, URI resource, String action);
+
+ /**
+ * The primary authorization method. The isAuthorized() methods call this method
+ * after converting their arguments into the appropriate attribute collection type.
+ * It returns a full AzResult, including authorization status, decision, and
+ * obligations.
+ *
+ * This method performs two steps prior to invoking the configured AuthorizationProvider
+ * to evaluate the request: First, it acquires the current AzEnvironment attributes by
+ * calling the Security Context service. Second, it calls the Role Mapping service to
+ * determine which roles the subject has, and adds the resulting role attributes into
+ * the AzSubject.
+ *
+ * @param subject The attributes collection representing the Subject for which an authorization
+ * decision is requested.
+ * @param resource The attributes collection representing the resource for which access is
+ * being requested.
+ * @param action The attributes collection representing the action, with respect to the resource,
+ * for which access is being requested. A null action is interpreted as all
+ * actions, however all actions may also be represented by the AzAction instance.
+ * See <code>{@link org.glassfish.security.services.api.authorization.AzAction}</code>.
+ * @return The AzResult indicating the result of the access decision.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ */
+ public AzResult getAuthorizationDecision(AzSubject subject, AzResource resource, AzAction action);
+
+ /**
+ * Converts a Java Subject into a typed attributes collection.
+ *
+ * @param subject The Subject to convert.
+ * @return The resulting AzSubject.
+ * @throws IllegalArgumentException Given null or illegal subject
+ */
+ public AzSubject makeAzSubject(Subject subject);
+
+ /**
+ * Converts a resource, expressed as a URI, into a typed attributes collection.
+ * <p>
+ * Query parameters in the given URI are appended to this
+ * <code>AzResource</code> instance attributes collection.
+ *
+ * @param resource The URI to convert.
+ * @return The resulting AzResource.
+ * @throws IllegalArgumentException Given null or illegal resource
+ */
+ public AzResource makeAzResource(URI resource);
+
+ /**
+ * Converts an action, expressed as a String, into a typed attributes collection.
+ *
+ * @param action The action to convert. null or "*" represents all actions.
+ * @return The resulting AzAction.
+ */
+ public AzAction makeAzAction(String action);
+
+ // TODO: What if multiple providers? Rollback/closeWithoutChange? Would delete remove an existing PolicyDeploymentContext?
+ /**
+ * Finds an existing PolicyDeploymentContext, or create a new one if one does not
+ * already exist for the specified appContext. The context will be returned in
+ * an "open" state, and will stay that way until commit() or delete() is called.
+ *
+ * @param appContext The application context for which the PolicyDeploymentContext
+ * is desired.
+ * @return The resulting PolicyDeploymentContext,
+ * null if the configured providers do not support this feature.
+ * @throws IllegalStateException Service was not initialized.
+ */
+ public PolicyDeploymentContext findOrCreateDeploymentContext(String appContext);
+
+ /**
+ * This interface represents a PolicyDeploymentContext as returned by the Authorization
+ * Service's findOrCreateDeploymentContext() method. The PolicyDeploymentContext is used
+ * to configure authorization policy for an application (or server administration) context.
+ * It represents the body of policy that applies to the given context.
+ *
+ * A PolicyDeploymentContext is always in one of three states: open, closed/inService,
+ * or deleted. When returned by the Authorization service, a context is in an open state.
+ * Policies can be added or deleted while in the open state, but the context is not
+ * in service. Upon calling commit(), the context is closed and the policies are place
+ * in service. Upon calling delete(), the context is taken out of service and the policies
+ * are deleted from the Authorization Provider.
+ */
+ public interface PolicyDeploymentContext {
+
+ public void addRolePolicy(String role, String resource, String action);
+
+ public void addUncheckedPolicy(String resource, String action);
+
+ public void addExcludedPolicy(String resource, String action);
+
+ public void removeRolePolicy(String role);
+
+ public void removeRolePolicies();
+
+ public void removeUncheckedPolicies();
+
+ public void removeExcludedPolicies();
+
+ public void commit();
+
+ public void delete();
+ }
+
+
+ /**
+ * Appends the given <code>{@link org.glassfish.security.services.api.authorization.AzAttributeResolver}</code>
+ * instance to the internal ordered list of <code>AzAttributeResolver</code> instances,
+ * if not currently in the list based on
+ * <code>{@link org.glassfish.security.services.api.authorization.AzAttributeResolver#equals}</code>.
+ *
+ * @param resolver The <code>AzAttributeResolver</code> instance to append.
+ * @return true if the <code>AzAttributeResolver</code> was added,
+ * false if the <code>AzAttributeResolver</code> was already in the list.
+ * @throws IllegalArgumentException Given AzAttributeResolver was null.
+ */
+ public boolean appendAttributeResolver(AzAttributeResolver resolver);
+
+
+ /**
+ * Replaces the internal list of <code>AttributeResolver</code> instances
+ * with the given list. If multiple equivalent instances exist in the given list,
+ * only the first such instance will be inserted.
+ *
+ * @param resolverList Replacement list of <code>AzAttributeResolver</code> instances
+ * @throws IllegalArgumentException Given AzAttributeResolver list was null.
+ */
+ public void setAttributeResolvers(List<AzAttributeResolver> resolverList);
+
+
+ /**
+ * Determines the current list of <code>AttributeResolver</code> instances,
+ * in execution order.
+ *
+ * @return The current list of AttributeResolver instances,
+ * in execution order.
+ */
+ public List<AzAttributeResolver> getAttributeResolvers();
+
+
+ /**
+ * Removes all <code>AttributeResolver</code> instances from the current
+ * internal list of <code>AttributeResolver</code> instances.
+ *
+ * @return true if any <code>AttributeResolver</code> instances were removed,
+ * false if the list was empty.
+ */
+ public boolean removeAllAttributeResolvers();
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAction.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAction.java
new file mode 100755
index 0000000..b033580
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAction.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+/**
+ * Extends the AzAttributes interface to provide a type-safe interface for Action attributes.
+ */
+public interface AzAction extends AzAttributes {
+
+ /**
+ * The name of this collection. For example, this name may be used to
+ * qualify attributes by collection type in XACML.
+ */
+ String NAME = "ACTION";
+
+ /**
+ * Determines the action represented as a string.
+ * @return The represented action, null represents all actions
+ */
+ String getAction();
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributeResolver.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributeResolver.java
new file mode 100755
index 0000000..55f8545
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributeResolver.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import org.glassfish.security.services.api.common.Attribute;
+
+
+/**
+ * <code>AzAttributeResolver</code> provides runtime resolution of attributes.
+ * <p>
+ * This is used to obtain attribute values which are not available in the
+ * corresponding AzAttributes collection. Implementations may obtain
+ * the attribute values from arbitrary sources, including
+ * calculation or from remote servers. Since
+ * an <code>AzAttributeResolver</code> may be called frequently during time-
+ * sensitive operations, caching and other performance-enhancing techniques
+ * should be used by the implementation.
+ */
+
+public interface AzAttributeResolver {
+
+ /**
+ * Resolves the specified attribute.
+ *
+ * @param attributeName The attribute to resolve.
+ * @param collection The read-only collection within which the attribute resides.
+ * @param environment The read-only operational context
+ * @return The resolved attribute, null if unresolvable.
+ */
+ public Attribute resolve(
+ String attributeName,
+ AzAttributes collection,
+ AzEnvironment environment );
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributes.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributes.java
new file mode 100755
index 0000000..f8d27ee
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzAttributes.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import org.glassfish.security.services.api.common.Attributes;
+
+/**
+ * Extends the Attributes interface to provide an abstract layer
+ * specifically for Authorization attributes.
+ */
+public interface AzAttributes extends Attributes {
+
+ /**
+ * Determines a name to denote this collection of attributes.
+ * <p>
+ * For example, this name may be used to qualify attributes by collection
+ * type in XACML.
+ *
+ * @return The collection name
+ */
+ String getName();
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzEnvironment.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzEnvironment.java
new file mode 100755
index 0000000..790ae98
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzEnvironment.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+/**
+ * Extends the AzAttributes interface to provide a type-safe interface for Environment attributes.
+ */
+public interface AzEnvironment extends AzAttributes {
+
+ /**
+ * The name of this collection. For example, this name may be used to
+ * qualify attributes by collection type in XACML.
+ */
+ String NAME = "ENVIRONMENT";
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzObligations.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzObligations.java
new file mode 100755
index 0000000..de2784e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzObligations.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+/**
+ * Extends the AzAttributes interface to provide a type-safe interface for Obligations attributes.
+ */
+public interface AzObligations extends AzAttributes {
+
+ /**
+ * The name of this collection. For example, this name may be used to
+ * qualify attributes by collection type in XACML.
+ */
+ String NAME = "OBLIGATIONS";
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResource.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResource.java
new file mode 100755
index 0000000..e5ad1d0
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import java.net.URI;
+
+/**
+ * Extends the AzAttributes interface to provide a type-safe interface for Resource attributes.
+ */
+public interface AzResource extends AzAttributes {
+
+ /**
+ * The name of this collection. For example, this name may be used to
+ * qualify attributes by collection type in XACML.
+ */
+ String NAME = "RESOURCE";
+
+
+ /**
+ * Determines the URI representing this resource.
+ * @return The URI representing this resource, never null.
+ */
+ public URI getUri();
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResult.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResult.java
new file mode 100755
index 0000000..d844493
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzResult.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+/**
+ * The AzResult class represents the result of an authorization decision. The result includes three distinct results:
+ * A result status, which indicates whether the call was successful or not, and may indicate a reason for a failed call;
+ * an authorization decision, which is valid only if the status is "OK", and obligations, which represent actions the
+ * calling code must take if it proceeds to access the resource in question. Obligations are expressed as attributes;
+ * the meaning of any specific obligation is established by an out-of-band agreement between the PDP and the PEP.
+ */
+public interface AzResult {
+
+ /**
+ * The possible authorization decision values. These carry the same meaning as the corresponding
+ * decision values defined by XACML 2.0 and later.
+ */
+ public enum Decision { PERMIT, DENY, INDETERMINATE, NOT_APPLICABLE };
+ /**
+ * The possible authorization status values. These carry the same meaning as the corresponding
+ * status values defined by XACML 2.0 and later.
+ */
+ public enum Status { OK, MISSING_ATTRIBUTE, PROCESSING_ERROR, SYNTAX_ERROR };
+
+ /**
+ * Get the authorization decision value for this AzResult.
+ *
+ * @return The Decision value.
+ */
+ public Decision getDecision();
+
+ /**
+ * Get the authorization status value for this AzResult.
+ *
+ * @return The Status value.
+ */
+ public Status getStatus();
+
+ /**
+ * Return the obligations that apply to this result.
+ *
+ * @return The AzObligations.
+ */
+ public AzObligations getObligations();
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzSubject.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzSubject.java
new file mode 100755
index 0000000..30080fa
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/AzSubject.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import javax.security.auth.Subject;
+
+/**
+ * Extends the AzAttributes interface to provide a type-safe interface for Subject attributes.
+ */
+public interface AzSubject extends AzAttributes {
+
+ /**
+ * The name of this collection. For example, this name may be used to
+ * qualify attributes by collection type in XACML.
+ */
+ String NAME = "SUBJECT";
+
+
+ /**
+ * Determines the <code>{@link javax.security.auth.Subject}</code>
+ * represented by this AzSubject.
+ * @return The represented Subject
+ */
+ Subject getSubject() ;
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/RoleMappingService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/RoleMappingService.java
new file mode 100755
index 0000000..4fb76ab
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/authorization/RoleMappingService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+import java.net.URI;
+import javax.security.auth.Subject;
+
+import org.glassfish.security.services.api.SecurityService;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * The <code>RoleMappingService</code> provides functions that determine a user's role.
+ */
+@Contract
+public interface RoleMappingService extends SecurityService {
+
+ /**
+ * Determine whether the user (<code>Subject</code>) has the indicated role
+ * for a given resource (<code>URI</code>) and application context.
+ *
+ * @param appContext The application context for the query (can be null).
+ * @param subject The target <code>Subject</code>.
+ * @param resource The <code>URI</code> resource for the query.
+ * @param role The target role.
+ * @return true if the user has the specified role.
+ *
+ * @throws IllegalArgumentException for a <code>null</code> subject or resource
+ * @throws IllegalStateException if the service was not initialized.
+ */
+ public boolean isUserInRole(String appContext, Subject subject, URI resource, String role);
+
+ /**
+ * Determine whether the user (<code>AzSubject</code>) has the indicated role
+ * for a given resource (<code>AzResource</code>) and application context.
+ *
+ * @param appContext The application context for the query (can be null).
+ * @param subject The target <code>{@link org.glassfish.security.services.api.authorization.AzSubject}</code>.
+ * @param resource The <code>{@link org.glassfish.security.services.api.authorization.AzResource}</code> for the query.
+ * @param role The target role.
+ * @return true if the user has the specified role.
+ *
+ * @throws IllegalArgumentException for a <code>null</code> subject or resource
+ * @throws IllegalStateException if the service was not initialized.
+ */
+ public boolean isUserInRole(String appContext, AzSubject subject, AzResource resource, String role);
+
+ /**
+ * Find an existing <code>RoleDeploymentContext</code>, or create a new one if one does not
+ * already exist for the specified application context. The role deployment context will be
+ * returned in an "open" state, and will stay that way until commit() or delete() is called.
+ *
+ * @param appContext The application context for which the <code>RoleDeploymentContext</code> is desired.
+ * @return The resulting <code>RoleDeploymentContext</code> or <code>null</code> if the configured providers
+ * do not support this feature.
+ *
+ * @throws IllegalStateException if the service was not initialized.
+ */
+ public RoleDeploymentContext findOrCreateDeploymentContext(String appContext);
+
+ /**
+ * This interface represents a <code>RoleDeploymentContext</code> as returned by the Role Mapping
+ * Service's findOrCreateDeploymentContext() method. The <code>RoleDeploymentContext</code> is used
+ * to configure role mapping policy for an application (or server administration) context.
+ * It represents the body of policy that applies to the given context.
+ *
+ * A <code>RoleDeploymentContext</code> is always in one of three states: open, closed/inService,
+ * or deleted. When returned by the Role Mapping service, a context is in an open state.
+ * Policies can be added or deleted while in the open state, but the context is not
+ * in service. Upon calling commit(), the context is closed and the policies are place
+ * in service. Upon calling delete(), the context is taken out of service and the policies
+ * are deleted from the Role Mapping Provider.
+ */
+ public interface RoleDeploymentContext {
+
+ public void addMapping(String role, String[] users, String[] groups);
+
+ public void removeMapping(String role, String[] users, String[] groups);
+
+ public void removeRole(String role);
+
+ public void commit();
+
+ public void delete();
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attribute.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attribute.java
new file mode 100755
index 0000000..800c91f
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attribute.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.common;
+
+
+import java.util.Set;
+
+/**
+ * The Attribute interface defines an interface for interacting with individual Attributes. It is a read-only interface.
+ * <br>
+ * Note that, because the collection used to hold attribute values is a Set, the attribute can be multi-valued. Each value
+ * must be distinct, however -- it is not a bag that can contain multiple instances of the same value.
+ */
+public interface Attribute {
+
+ /**
+ * Get the name of this attribute.
+ *
+ * @return The name.
+ */
+ public String getName();
+
+ /**
+ * Get a count of the number of values this attribute has (0-n).
+ *
+ * @return The value count.
+ */
+ public int getValueCount();
+
+ /**
+ * Get the first value from the Set of attribute values, or null if the attribute has no values.
+ * This is a shorthand method that should be useful for single-valued attributes, but note that
+ * there are no guarantees about which value is returned in the case that there are multiple values.
+ * The value returned will be whichever value the underlying Set implementation returns first.
+ *
+ * @return The attribute value.
+ */
+ public String getValue();
+
+ /**
+ * Get the Set of values for this attribute. The Set returned is a copy of the original; changes
+ * to this Set will not affect the original.
+ *
+ * @return The attribute values Set.
+ */
+ public Set<String> getValues();
+
+ /**
+ * Return the attributes values as a String array. Note that this array can be zero-length
+ * in the case that there are no values.
+ *
+ * @return The attribute values array.
+ */
+ public String[] getValuesAsArray();
+
+ public void addValue(String value);
+ public void addValues(Set<String> values);
+ public void addValues(String[] values);
+
+ public void removeValue(String value);
+ public void removeValues(Set<String> values);
+ public void removeValues(String[] values);
+
+ public void clear();
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attributes.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attributes.java
new file mode 100755
index 0000000..322b8f8
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/common/Attributes.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.common;
+
+
+import java.util.Set;
+
+/**
+ * An interface that represents a collectoin of Attributes. Unlike the Attribute interface, this interface
+ * is not read-only. Methods are provided to update the underlying collection by adding, removing, or updating
+ * the attributes it holds.
+ *
+ * There is no factory method on this interface; instead, services that take Attributes parameters have
+ * methods for generating instances of Attributes appropriate to the purpose at hand.
+ */
+public interface Attributes {
+
+ /**
+ * Get a count of the number of Attributes (not attribute values) in this Attributes object.
+ *
+ * @return The attribute count.
+ */
+ public int getAttributeCount();
+
+ /**
+ * Get the attribute names, as a Set. This set is read-only; updating it will not change the
+ * underlying attributes collection.
+ *
+ * @return The attribute names Set.
+ */
+ public Set<String> getAttributeNames();
+
+ /**
+ * Get the Attribute object for the named attribute, if present.
+ *
+ * @param name The name of the Attribute to get.
+ * @return The Attribute, or null if an attribute by that name is not present.
+ */
+ public Attribute getAttribute(String name);
+
+ /**
+ * Get the value of the specified attribute, if present. Note that, for multi-valued attributes,
+ * The value returned is whichever value is returned first by the underlying Set implementation;
+ * there are no ordering guarantees. As such, this method is primarily useful as a shorthand
+ * method for attributes known (or expected) by the caller to be single-valued.
+ *
+ * Note also that it is not possible, using this method, to distinguish between a missing attribute
+ * and an attribute that is present but has no values. In both cases, null is returned.
+ *
+ * @param name The name of the attribute whose value is wanted.
+ * @return The attribute value, or null if the attribute is missing or has no values.
+ */
+ public String getAttributeValue(String name);
+
+ /**
+ * Get the Set of values for the specified attribute, if present.
+ *
+ * @param name The name of the attribute whose values are wanted.
+ * @return The Set of values, or null if the attribute is not present in the collection. If the
+ * attribute is present but has no values, an empty Set is returned.
+ */
+ public Set<String> getAttributeValues(String name);
+
+ /**
+ * Get the set of values for the specified attribute as a String array.
+ *
+ * @param name The name of the attribute whose values are wanted.
+ * @return The array of values, or null if the attribute is not present in the collection. If the
+ * attribute is present but has no values, a zero-length array is returned.
+ */
+ public String[] getAttributeValuesAsArray(String name);
+
+ /**
+ * Add the specified attribute to the attributes collection. Remove any existing values
+ * if the replace parameter is true, otherwise add the new value to the existing values.
+ * Duplicate values are silently dropped.
+ *
+ * @param name The name of the attribute to add.
+ * @param value The single attribute value to add.
+ * @param replace If true, replace the existing attribute and any existing values. If false,
+ * add the new value to those that are already present.
+ */
+ public void addAttribute(String name, String value, boolean replace);
+
+ /**
+ * Add the specified attribute to the attributes collection. Remove any existing values
+ * if the replace parameter is true, otherwise add the new values to the existing values.
+ * Duplicate values are silently dropped.
+ *
+ * @param name The name of the attribute to add.
+ * @param value The Set of values to add.
+ * @param replace If true, replace the existing attribute and any existing values. If false,
+ * add the new values to those that are already present.
+ */
+ public void addAttribute(String name, Set<String> values, boolean replace);
+
+ /**
+ * Add the specified attribute to the attributes collection. Remove any existing values
+ * if the replace parameter is true, otherwise add the new values to the existing values.
+ * Duplicate values are silently dropped.
+ *
+ * @param name The name of the attribute to add.
+ * @param value The array of values to add.
+ * @param replace If true, replace the existing attribute and any existing values. If false,
+ * add the new values to those that are already present.
+ */
+ public void addAttribute(String name, String[] values, boolean replace);
+
+ /**
+ * Remove the specified attribute from the collection.
+ *
+ * @param name The name of the attribute to remove.
+ */
+ public void removeAttribute(String name);
+
+ /**
+ * Remove the specified value from the named attribute.
+ *
+ * @param name The name of the attribute from which to remove a value.
+ * @param value The value to remove. A value will be removed only if it exactly matches this parameter.
+ */
+ public void removeAttributeValue(String name, String value);
+
+ /**
+ * Remove the specified values from the named attribute.
+ *
+ * @param name The name of the attribute from which to remove the values.
+ * @param value The Set of values to remove. Only values that exactly match values in this Set will be removed.
+ */
+ public void removeAttributeValues(String name, Set<String> values);
+
+ /**
+ * Remove the specified values from the named attribute.
+ *
+ * @param name The name of the attribute from which to remove the values.
+ * @param value The array of values to remove. Only values that exactly match values in this array will be removed.
+ */
+ public void removeAttributeValues(String name, String[] values);
+
+ /**
+ * Remove all values associated with the named attribute, but do not remove
+ * the attribute from the collection.
+ *
+ * @param name The name of the attribute whose values should be removed.
+ */
+ public void removeAllAttributeValues(String name);
+
+ /**
+ * Removes all attributes from the collection.
+ */
+ public void clear();
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/api/context/SecurityContextService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/context/SecurityContextService.java
new file mode 100755
index 0000000..9b8088e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/api/context/SecurityContextService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.context;
+
+
+import org.glassfish.security.services.api.common.Attributes;
+
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * The Security Context Service maintains context needed by various security
+ * services. It is scoped per-thread (though this does not preclude it from
+ * providing access to context that has different scope).
+ */
+
+@Contract
+public interface SecurityContextService {
+
+ /**
+ * Return the Environment attributes collection associated with the current thread.
+ *
+ * @return The environment attributes.
+ */
+ public Attributes getEnvironmentAttributes();
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CLIUtil.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CLIUtil.java
new file mode 100644
index 0000000..4e71fef
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CLIUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.commands;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.ActionReport;
+import org.glassfish.security.services.config.SecurityConfiguration;
+import org.glassfish.security.services.config.SecurityConfigurations;
+import org.glassfish.security.services.config.SecurityProvider;
+
+/**
+ *
+ * @author tjquinn
+ */
+public class CLIUtil {
+
+ public static SecurityConfiguration findSecurityConfiguration(
+ final Domain domain,
+ final String serviceName,
+ final ActionReport report) {
+ // Lookup the security configurations
+ SecurityConfigurations secConfigs = domain.getExtensionByType(SecurityConfigurations.class);
+ if (secConfigs == null) {
+ report.setMessage("Unable to locate security configurations");
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return null;
+ }
+
+ // Get the security service
+ SecurityConfiguration ssc = secConfigs.getSecurityServiceByName(serviceName);
+ if (ssc == null) {
+ report.setMessage("Unable to locate security service: " + serviceName);
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return null;
+ }
+ return ssc;
+ }
+
+ public static SecurityProvider findSecurityProvider(
+ final Domain domain,
+ final String serviceName,
+ final String providerName,
+ final ActionReport report) {
+ // Get the security provider config
+ final SecurityConfiguration sc = findSecurityConfiguration(domain, serviceName, report);
+ if (sc == null) {
+ return null;
+ }
+ SecurityProvider provider = sc.getSecurityProviderByName(providerName);
+ if (provider == null) {
+ report.setMessage("Unable to locate security provider: " + providerName);
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return null;
+ }
+ return provider;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateLoginModuleConfig.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateLoginModuleConfig.java
new file mode 100644
index 0000000..ad427e9
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateLoginModuleConfig.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.commands;
+
+import java.beans.PropertyVetoException;
+import java.util.Properties;
+
+import javax.inject.Inject;
+
+import org.glassfish.security.services.config.SecurityConfiguration;
+
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.glassfish.hk2.api.PerLookup;
+
+import org.glassfish.security.services.config.LoginModuleConfig;
+import org.glassfish.security.services.config.SecurityConfigurations;
+import org.glassfish.security.services.config.SecurityProvider;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+
+/**
+ * General create LoginModule config command.
+ */
+@Service(name="_create-login-module-config")
+@PerLookup
+@ExecuteOn(RuntimeType.DAS)
+@TargetType(CommandTarget.DAS)
+public class CreateLoginModuleConfig implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ @Param(optional = false)
+ private String serviceName;
+
+ @Param(optional = false)
+ private String providerName;
+
+ @Param(optional = false)
+ private String moduleClass;
+
+ @Param(optional = false)
+ private String controlFlag;
+
+ @Param(optional = true, separator = ':')
+ private Properties configuration;
+
+ @Param(primary = true)
+ private String name;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.NewChild(type=LoginModuleConfig.class)
+ private SecurityProvider provider;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ SecurityProvider provider = CLIUtil.findSecurityProvider(domain, serviceName, providerName, context.getActionReport());
+ return (provider != null);
+ }
+
+
+ /**
+ * Execute the create-login-module-config admin command.
+ */
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ // Add LoginModule configuration to the security provider setup
+ // TODO - Add validation logic of the LoginModule config attributes
+ LoginModuleConfig config = null;
+ try {
+ config = (LoginModuleConfig) ConfigSupport.apply(new SingleConfigCode<SecurityProvider>() {
+ @Override
+ public Object run(SecurityProvider param) throws PropertyVetoException, TransactionFailure {
+ LoginModuleConfig lmConfig = param.createChild(LoginModuleConfig.class);
+ lmConfig.setName(name);
+ lmConfig.setModuleClass(moduleClass);
+ lmConfig.setControlFlag(controlFlag);
+ // TODO - Should prevent multiple security provider config entries
+ param.getSecurityProviderConfig().add(lmConfig);
+ return lmConfig;
+ }
+ }, provider);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to create login module config: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ return;
+ }
+
+ // Setup LoginModule configuration options
+ if ((config != null) && (configuration != null) && (!configuration.isEmpty())) {
+ try {
+ ConfigSupport.apply(new SingleConfigCode<LoginModuleConfig>() {
+ @Override
+ public Object run(LoginModuleConfig param) throws PropertyVetoException, TransactionFailure {
+ for (Object configPropName: configuration.keySet()) {
+ Property prop = param.createChild(Property.class);
+ String propName = (String) configPropName;
+ prop.setName(propName);
+ prop.setValue(configuration.getProperty(propName));
+ param.getProperty().add(prop);
+ }
+ return param;
+ }
+ }, config);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to create login module options: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ }
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityProvider.java
new file mode 100644
index 0000000..481bfe3
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityProvider.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.commands;
+
+import java.beans.PropertyVetoException;
+
+import javax.inject.Inject;
+
+import org.glassfish.security.services.config.SecurityConfiguration;
+
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+import org.glassfish.hk2.api.PerLookup;
+
+import org.glassfish.security.services.config.SecurityConfigurations;
+import org.glassfish.security.services.config.SecurityProvider;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+
+/**
+ * General create security provider command.
+ */
+@Service(name="_create-security-provider")
+@PerLookup
+@ExecuteOn(RuntimeType.DAS)
+@TargetType(CommandTarget.DAS)
+public class CreateSecurityProvider implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ @Param(optional = false)
+ private String serviceName;
+
+ @Param(optional = false)
+ private String providerName;
+
+ @Param(optional = false)
+ private String providerType;
+
+ @Param(primary = true)
+ private String name;
+
+ @Inject
+ private Domain domain;
+
+ @AccessRequired.NewChild(type=SecurityProvider.class)
+ private SecurityConfiguration securityServiceConfiguration;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ securityServiceConfiguration = CLIUtil.findSecurityConfiguration(domain,
+ serviceName, context.getActionReport());
+ return (securityServiceConfiguration != null);
+ }
+
+ /**
+ * Execute the create-security-provider admin command.
+ */
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ // Add security provider configuration to the service
+ // TODO - Add validation logic required for security provider attributes
+ try {
+ ConfigSupport.apply(new SingleConfigCode<SecurityConfiguration>() {
+ @Override
+ public Object run(SecurityConfiguration param) throws PropertyVetoException, TransactionFailure {
+ SecurityProvider providerConfig = param.createChild(SecurityProvider.class);
+ providerConfig.setName(name);
+ providerConfig.setType(providerType);
+ providerConfig.setProviderName(providerName);
+ param.getSecurityProviders().add(providerConfig);
+ return providerConfig;
+ }
+ }, securityServiceConfiguration);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to create security provider: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ }
+ }
+
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityService.java
new file mode 100644
index 0000000..0c9bf64
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/CreateSecurityService.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.commands;
+
+import java.beans.PropertyVetoException;
+import java.util.Properties;
+
+import javax.inject.Inject;
+
+import org.glassfish.security.services.config.SecurityConfiguration;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.api.admin.ExecuteOn;
+import org.glassfish.api.admin.RuntimeType;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+import org.glassfish.security.services.config.AuthenticationService;
+import org.glassfish.security.services.config.SecurityConfigurations;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import org.glassfish.api.admin.AccessRequired;
+import org.glassfish.api.admin.AdminCommandSecurity;
+
+/**
+ * General create security service command.
+ */
+@Service(name="_create-security-service")
+@PerLookup
+@ExecuteOn(RuntimeType.DAS)
+@TargetType(CommandTarget.DAS)
+public class CreateSecurityService implements AdminCommand, AdminCommandSecurity.Preauthorization {
+ private static final String AUTHENTICATION = "authentication";
+
+ @Param(optional = false)
+ private String serviceType;
+
+ @Param(defaultValue = "false", optional = true)
+ private Boolean enableDefault;
+
+ @Param(optional = true, separator = ':')
+ private Properties configuration;
+
+ @Param(primary = true)
+ private String serviceName;
+
+ @Inject
+ private Domain domain;
+
+ // Service configuration type and handler
+ private Class<? extends SecurityConfiguration> clazzServiceType;
+ private ServiceConfigHandler<? extends SecurityConfiguration> serviceConfigHandler;
+
+ @AccessRequired.To("create")
+ private SecurityConfigurations secConfigs;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+ secConfigs = getSecurityConfigurations(report);
+ return secConfigs != null;
+ }
+
+ /**
+ * Execute the create-security-service admin command.
+ */
+ @Override
+ public void execute(AdminCommandContext context) {
+ final ActionReport report = context.getActionReport();
+
+ // Setup the service type and configuration handler
+ if (AUTHENTICATION.equalsIgnoreCase(serviceType)) {
+ clazzServiceType = AuthenticationService.class;
+ serviceConfigHandler = new AuthenticationConfigHandler();
+ }
+ else {
+ report.setMessage("Invalid security service type specified: " + serviceType);
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+
+ // Add service configuration to the security configurations
+ // TODO - Add validation logic required for base service configuration
+ SecurityConfiguration config = null;
+ try {
+ config = (SecurityConfiguration) ConfigSupport.apply(new SingleConfigCode<SecurityConfigurations>() {
+ @Override
+ public Object run(SecurityConfigurations param) throws PropertyVetoException, TransactionFailure {
+ SecurityConfiguration svcConfig = param.createChild(clazzServiceType);
+ svcConfig.setName(serviceName);
+ svcConfig.setDefault(enableDefault);
+ param.getSecurityServices().add(svcConfig);
+ return svcConfig;
+ }
+ }, secConfigs);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to create security service: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ return;
+ }
+
+ // Configure the specific service type settings
+ // TODO - Add validation logic required for specific service configuration
+ if ((config != null) && (configuration != null) && (!configuration.isEmpty())) {
+ serviceConfigHandler.setupConfiguration(report, config);
+ }
+ }
+
+ /**
+ * Base class for service type configuration handling
+ */
+ private abstract class ServiceConfigHandler<T extends SecurityConfiguration> {
+ abstract T setupConfiguration(ActionReport report, SecurityConfiguration securityServiceConfig);
+ }
+
+ /**
+ * Handle the authentication service configuration
+ */
+ private class AuthenticationConfigHandler extends ServiceConfigHandler<AuthenticationService> {
+ @Override
+ public AuthenticationService setupConfiguration(ActionReport report, SecurityConfiguration securityServiceConfig) {
+ // TODO - Additional type checking needed?
+ AuthenticationService config = (AuthenticationService) securityServiceConfig;
+ try {
+ config = (AuthenticationService) ConfigSupport.apply(new SingleConfigCode<AuthenticationService>() {
+ @Override
+ public Object run(AuthenticationService param) throws PropertyVetoException, TransactionFailure {
+ // Look at the use password credential setting
+ Boolean usePassCred = Boolean.valueOf(configuration.getProperty("use-password-credential"));
+ param.setUsePasswordCredential(usePassCred.booleanValue());
+ return param;
+ }
+ }, config);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to configure authentication service: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ return null;
+ }
+
+ // Return the updated configuration object
+ return config;
+ }
+ }
+
+ private SecurityConfigurations getSecurityConfigurations(final ActionReport report) {
+ // Lookup or Create the security configurations
+ SecurityConfigurations result = domain.getExtensionByType(SecurityConfigurations.class);
+ if (result == null) {
+ try {
+ result = (SecurityConfigurations) ConfigSupport.apply(new SingleConfigCode<Domain>() {
+ @Override
+ public Object run(Domain wDomain) throws PropertyVetoException, TransactionFailure {
+ SecurityConfigurations s = wDomain.createChild(SecurityConfigurations.class);
+ wDomain.getExtensions().add(s);
+ return s;
+ }
+ }, domain);
+ } catch (TransactionFailure transactionFailure) {
+ report.setMessage("Unable to create security configurations: " + transactionFailure.getMessage());
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ report.setFailureCause(transactionFailure);
+ }
+ }
+ return result;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/LDAPAdminAccessConfigurator.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/LDAPAdminAccessConfigurator.java
new file mode 100644
index 0000000..4b7452d
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/commands/LDAPAdminAccessConfigurator.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.commands;
+
+//import com.sun.enterprise.config.serverbeans.*;
+import com.sun.enterprise.config.serverbeans.*;
+import com.sun.enterprise.security.auth.realm.Realm;
+import com.sun.enterprise.security.auth.realm.ldap.LDAPRealm;
+import com.sun.enterprise.util.i18n.StringManager;
+import com.sun.enterprise.util.StringUtils;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import org.glassfish.security.services.impl.ServiceLogging;
+import java.beans.PropertyChangeEvent;
+import org.glassfish.api.ActionReport;
+import org.glassfish.api.Param;
+import org.glassfish.api.admin.AdminCommand;
+import org.glassfish.api.admin.AdminCommandContext;
+import org.glassfish.internal.api.Target;
+import javax.inject.Inject;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.ConfigSupport;
+import org.jvnet.hk2.config.SingleConfigCode;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import java.beans.PropertyVetoException;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.naming.AuthenticationNotSupportedException;
+import org.glassfish.api.admin.*;
+import org.glassfish.config.support.CommandTarget;
+import org.glassfish.config.support.TargetType;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.security.services.config.AuthenticationService;
+import org.glassfish.security.services.config.LoginModuleConfig;
+import org.glassfish.security.services.config.SecurityConfigurations;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.config.SecurityProviderConfig;
+import com.sun.enterprise.security.auth.login.LDAPLoginModule;
+import org.jvnet.hk2.config.RetryableException;
+import org.jvnet.hk2.config.Transaction;
+
+/** A convenience command to configure LDAP for administration. There are several properties and attributes that
+ * user needs to remember and that's rather user unfriendly. That's why this command is being developed.
+ * @author केदार (km@dev.java.net)
+ * @since GlassFish V3
+ */
+@Service(name="configure-ldap-for-admin")
+@PerLookup
+@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
+@TargetType({CommandTarget.DAS,CommandTarget.STANDALONE_INSTANCE,CommandTarget.CLUSTER, CommandTarget.CONFIG})
+@RestEndpoints({
+ @RestEndpoint(configBean=Domain.class,
+ opType=RestEndpoint.OpType.POST,
+ path="configure-ldap-for-admin",
+ description="configure-ldap-for-admin")
+})
+public class LDAPAdminAccessConfigurator implements AdminCommand, AdminCommandSecurity.Preauthorization {
+
+ @Param (name="basedn", shortName="b", optional=false)
+ public volatile String basedn;
+
+ @Param(name="url", optional=true)
+ public volatile String url = "ldap://localhost:389"; // the default port for LDAP on localhost
+
+
+ @Param(name="ldap-group", shortName="g", optional=true)
+ public volatile String ldapGroupName;
+
+ @Inject
+ Target targetService;
+
+ @Inject
+ private ConfigBeansUtilities configBeansUtilities;
+
+ //TODO: not sure what to do with --target here
+ @Param(name = "target", optional = true, defaultValue =
+ SystemPropertyConstants.DEFAULT_SERVER_INSTANCE_NAME)
+ private String target;
+
+ private final static String ADMIN_SERVER = "server"; //this needs to be at central place, oh well
+ private static final StringManager lsm = StringManager.getManager(LDAPAdminAccessConfigurator.class);
+ private static final String DIR_P = "directory";
+ private static final String BASEDN_P = "base-dn";
+ private static final String JAAS_P = "jaas-context";
+ private static final String JAAS_V = "ldapRealm";
+ public static final String LDAP_SOCKET_FACTORY = "java.naming.ldap.factory.socket";
+ public static final String DEFAULT_SSL_LDAP_SOCKET_FACTORY = "com.sun.enterprise.security.auth.realm.ldap.CustomSocketFactory";
+ public static final String LDAPS_URL = "ldaps://";
+
+ private static final Logger logger = Logger.getLogger(ServiceLogging.SEC_COMMANDS_LOGGER, ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+
+ private static final String AUTHENTICATION_SERVICE_PROVIDER_NAME = "adminAuth";
+ private static final String FILE_REALM_SECURITY_PROVIDER_NAME = "adminFile";
+ private static final String ADMIN_FILE_LM_NAME = "adminFileLM";
+
+ private Config asc;
+
+ @AccessRequired.To("update")
+ private AuthRealm adminAuthRealm;
+
+ @AccessRequired.To("update")
+ private AdminService adminService;
+
+ @AccessRequired.To("update")
+ private SecurityProvider fileRealmProvider;
+
+ @Inject
+ private SecurityConfigurations securityConfigs;
+
+ @Override
+ public boolean preAuthorization(AdminCommandContext context) {
+ asc = chooseConfig();
+ final SecurityService ss = asc.getSecurityService();
+ adminAuthRealm = getAdminRealm(ss);
+ adminService = asc.getAdminService();
+ final AuthenticationService adminAuthService = (AuthenticationService)
+ securityConfigs.getSecurityServiceByName(AUTHENTICATION_SERVICE_PROVIDER_NAME);
+ final ActionReport report = context.getActionReport();
+ if (adminAuthService == null) {
+ report.setMessage(lsm.getString("ldap.noExistingAtnService", AUTHENTICATION_SERVICE_PROVIDER_NAME));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ fileRealmProvider = adminAuthService.getSecurityProviderByName(FILE_REALM_SECURITY_PROVIDER_NAME);
+ if (fileRealmProvider == null) {
+ report.setMessage(lsm.getString("ldap.noExistingAtnProvider", FILE_REALM_SECURITY_PROVIDER_NAME));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ if ( ! "LoginModule".equals(fileRealmProvider.getType())) {
+ report.setMessage(lsm.getString("ldap.fileRealmProviderNotLoginModuleType",
+ FILE_REALM_SECURITY_PROVIDER_NAME,
+ adminAuthService.getName(),
+ fileRealmProvider.getType()));
+ report.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return false;
+ }
+ return true;
+ }
+
+
+
+ /** Field denoting the name of the realm used for administration. This is fixed in entire of v3. Note that
+ * the same name is used in admin GUI's web.xml and sun-web.xml. The name of the realm is the key, the
+ * underlying backend (LDAP, File, Database) can change.
+ */
+ public static final String FIXED_ADMIN_REALM_NAME = "admin-realm";
+ public static final String ORIG_ADMIN_REALM_NAME = "admin-realm-original";
+
+ @Override
+ public void execute(AdminCommandContext context) {
+ ActionReport rep = context.getActionReport();
+ StringBuilder sb = new StringBuilder();
+ if(url != null) {
+ if (!url.startsWith("ldap://") && !url.startsWith("ldaps://")) {
+ url = "ldap://" + url; //it's ok to accept just host:port
+ }
+ }
+ if (!pingLDAP(sb)) {
+ rep.setMessage(sb.toString());
+ rep.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ return;
+ }
+ try {
+ configure(sb);
+ //Realm.getInstance(FIXED_ADMIN_REALM_NAME).refresh();
+ rep.setMessage(sb.toString());
+ rep.setActionExitCode(ActionReport.ExitCode.SUCCESS);
+ } catch(TransactionFailure tf) {
+ rep.setMessage(tf.getMessage());
+ rep.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ } catch (PropertyVetoException e) {
+ rep.setMessage(e.getMessage());
+ rep.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ } catch (RetryableException re) {
+ rep.setMessage(re.getMessage());
+ rep.setActionExitCode(ActionReport.ExitCode.FAILURE);
+ }
+/*
+ catch (NoSuchRealmException e) {
+ ActionReport ar = rep.addSubActionsReport();
+ ar.setMessage(lsm.getString("realm.not.refreshed"));
+ ar.setActionExitCode(ActionReport.ExitCode.WARNING);
+ } catch (BadRealmException e) {
+ ActionReport ar = rep.addSubActionsReport();
+ ar.setMessage(lsm.getString("realm.not.refreshed"));
+ ar.setActionExitCode(ActionReport.ExitCode.WARNING);
+ }
+*/
+ }
+
+ private void configure(StringBuilder sb) throws TransactionFailure, PropertyVetoException, RetryableException {
+
+ //createBackupRealm(sb, getAdminRealm(asc.getSecurityService()), getNewRealmName(asc.getSecurityService()));
+
+ Transaction t = new Transaction();
+ final SecurityService w_asc = t.enroll(asc.getSecurityService());
+ AdminService w_adminSvc = t.enroll(asc.getAdminService());
+ deleteRealm(w_asc, sb);
+ createRealm(w_asc, sb);
+ configureAdminService(w_adminSvc);
+ updateSecurityProvider(t, fileRealmProvider, sb);
+ t.commit();
+ }
+
+/* private String getNewRealmName(SecurityService ss) {
+ List<AuthRealm> realms = ss.getAuthRealm();
+ String pref = ORIG_ADMIN_REALM_NAME + "-";
+ int index = 0; //last one
+ for (AuthRealm realm : realms) {
+ if (realm.getName().indexOf(pref) >= 0) {
+ index = Integer.parseInt(realm.getName().substring(pref.length()));
+ }
+ }
+ return pref + (index+1);
+ }*/
+
+ private void updateSecurityProvider(final Transaction t, final SecurityProvider w_sp,
+ final StringBuilder sb) throws TransactionFailure, PropertyVetoException {
+ for (SecurityProviderConfig spc : w_sp.getSecurityProviderConfig()) {
+ if ((spc instanceof LoginModuleConfig) && spc.getName().equals(ADMIN_FILE_LM_NAME)) {
+ final LoginModuleConfig w_lmConfig = t.enroll((LoginModuleConfig) spc);
+ w_lmConfig.setModuleClass(LDAPLoginModule.class.getName());
+ sb.append(lsm.getString("ldap.authProviderConfigOK", w_sp.getName()));
+ return;
+ }
+ }
+ throw new TransactionFailure(
+ lsm.getString("ldap.noAuthProviderConfig", w_sp.getName(), ADMIN_FILE_LM_NAME));
+ }
+
+ private AuthRealm getAdminRealm(SecurityService ss) {
+ List<AuthRealm> realms = ss.getAuthRealm();
+ for (AuthRealm realm : realms) {
+ if (FIXED_ADMIN_REALM_NAME.equals(realm.getName()))
+ return realm;
+ }
+ return null; //unlikely - represents an assertion
+ }
+
+ private void configureAdminService(AdminService as) throws PropertyVetoException, TransactionFailure {
+ as.setAuthRealmName(FIXED_ADMIN_REALM_NAME); //just in case ...
+ }
+
+ private void createRealm(SecurityService w_ss, final StringBuilder sb) throws TransactionFailure, PropertyVetoException {
+ AuthRealm ldapr = createLDAPRealm(w_ss);
+ w_ss.getAuthRealm().add(ldapr);
+ appendNL(sb,lsm.getString("ldap.realm.setup", FIXED_ADMIN_REALM_NAME));
+ }
+
+ // delete and create a new realm to replace it in a single transaction
+ private void deleteRealm(SecurityService w_ss, final StringBuilder sb) throws TransactionFailure {
+
+
+ AuthRealm oldAdminRealm = getAdminRealm(w_ss);
+ w_ss.getAuthRealm().remove(oldAdminRealm);
+ appendNL(sb,"...");
+ //AuthRealm ldapr = createLDAPRealm(ss);
+ //ss.getAuthRealm().add(ldapr);
+ //appendNL(sb,lsm.getString("ldap.realm.setup", FIXED_ADMIN_REALM_NAME));
+ }
+
+ // this had been called renameRealm, but in the SecurityConfigListener, the method authRealmUpdated actually does a create...
+/* private void createBackupRealm(final StringBuilder sb, AuthRealm realm, final String to) throws PropertyVetoException, TransactionFailure {
+ SingleConfigCode<AuthRealm> scc = new SingleConfigCode<AuthRealm>() {
+ @Override
+ public Object run(AuthRealm realm) throws PropertyVetoException, TransactionFailure {
+ appendNL(sb, lsm.getString("config.to.ldap", FIXED_ADMIN_REALM_NAME, to));
+ realm.setName(to);
+ return realm;
+ }
+ };
+ ConfigSupport.apply(scc, realm);
+ }*/
+
+ private AuthRealm createLDAPRealm(SecurityService ss) throws TransactionFailure, PropertyVetoException {
+ AuthRealm ar = ss.createChild(AuthRealm.class);
+ ar.setClassname(LDAPRealm.class.getName());
+ ar.setName(FIXED_ADMIN_REALM_NAME);
+ List<Property> props = ar.getProperty();
+
+ Property p = ar.createChild(Property.class);
+ p.setName(DIR_P);
+ p.setValue(url);
+ props.add(p);
+
+ p = ar.createChild(Property.class);
+ p.setName(BASEDN_P);
+ p.setValue(basedn);
+ props.add(p);
+
+ p = ar.createChild(Property.class);
+ p.setName(JAAS_P);
+ p.setValue(JAAS_V);
+ props.add(p);
+
+ if (ldapGroupName!= null) {
+ p = ar.createChild(Property.class);
+ p.setName(Realm.PARAM_GROUP_MAPPING);
+ p.setValue(ldapGroupName +"->asadmin"); //appears as gfdomain1->asadmin in domain.xml
+ props.add(p);
+ }
+
+ return ar;
+ }
+
+ private boolean pingLDAP(StringBuilder sb) {
+ Properties env = new Properties();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, url);
+
+ if (url != null && url.startsWith(LDAPS_URL)) {
+ env.put(LDAP_SOCKET_FACTORY,
+ DEFAULT_SSL_LDAP_SOCKET_FACTORY);
+ }
+ try {
+ new InitialContext(env);
+ appendNL(sb,lsm.getString("ldap.ok", url));
+ return true;
+ } catch (AuthenticationNotSupportedException anse) {
+ //CR 6944776
+ //If the server throws this error, it is up
+ //and is configured with Anonymous bind disabled.
+ //Ignore this error while configuring ldap for admin
+ appendNL(sb,lsm.getString("ldap.ok", url));
+ return true;
+ } catch(Exception e) {
+ appendNL(sb,lsm.getString("ldap.na", url, e.getClass().getName(), e.getMessage()));
+ if (logger.isLoggable(Level.FINE)) {
+ logger.log(Level.FINE, StringUtils.getStackTrace(e));
+ }
+ return false;
+ }
+ }
+
+ private static void appendNL(StringBuilder sb, String s) {
+ sb.append(s).append("%%%EOL%%%");
+ }
+
+ private Config chooseConfig() {
+ Server s = configBeansUtilities.getServerNamed(ADMIN_SERVER);
+ String ac = s.getConfigRef();
+ return targetService.getConfig(ac);
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilededLookup.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilededLookup.java
new file mode 100644
index 0000000..dd973d6
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilededLookup.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.security.PrivilegedAction;
+
+import org.glassfish.hk2.api.ServiceLocator;
+
+public class PrivilededLookup<T> implements PrivilegedAction<T> {
+
+ private ServiceLocator serviceLocator;
+ private Class<T> serviceClass;
+ private String serviceName;
+
+ /**
+ *
+ * @param serviceLocator the HK2 service locator
+ * @param serviceClass the protected HK2 service to be looked up
+ * @param serviceName the name of the service to be looked
+ */
+ public PrivilededLookup(ServiceLocator serviceLocator,
+ Class<T> serviceClass, String serviceName) {
+ this.serviceLocator = serviceLocator;
+ this.serviceClass = serviceClass;
+ this.serviceName = serviceName;
+ }
+
+ /**
+ *
+ * @param serviceLocator the HK2 service locator
+ * @param serviceClass the protected HK2 service to be looked up
+ */
+ public PrivilededLookup(ServiceLocator serviceLocator, Class<T> serviceClass) {
+ this(serviceLocator, serviceClass, null);
+ }
+
+ public T run() {
+ if (serviceName != null)
+ return serviceLocator.getService(serviceClass, serviceName);
+ else
+ return serviceLocator.getService(serviceClass);
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilegedLookup.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilegedLookup.java
new file mode 100644
index 0000000..64394bc
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/PrivilegedLookup.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.security.PrivilegedAction;
+
+import org.glassfish.hk2.api.ServiceLocator;
+
+public class PrivilegedLookup<T> implements PrivilegedAction<T> {
+
+ private ServiceLocator serviceLocator;
+ private Class<T> serviceClass;
+ private String serviceName;
+
+ /**
+ *
+ * @param serviceLocator the HK2 service locator
+ * @param serviceClass the protected HK2 service to be looked up
+ * @param serviceName the name of the service to be looked
+ */
+ public PrivilegedLookup(ServiceLocator serviceLocator,
+ Class<T> serviceClass, String serviceName) {
+ this.serviceLocator = serviceLocator;
+ this.serviceClass = serviceClass;
+ this.serviceName = serviceName;
+ }
+
+ /**
+ *
+ * @param serviceLocator the HK2 service locator
+ * @param serviceClass the protected HK2 service to be looked up
+ */
+ public PrivilegedLookup(ServiceLocator serviceLocator, Class<T> serviceClass) {
+ this(serviceLocator, serviceClass, null);
+ }
+
+ public T run() {
+ if (serviceName != null)
+ return serviceLocator.getService(serviceClass, serviceName);
+ else
+ return serviceLocator.getService(serviceClass);
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/Secure.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/Secure.java
new file mode 100644
index 0000000..609d74c
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/Secure.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+import org.glassfish.hk2.api.Metadata;
+
+/**
+ * Qualifier used to enable a security check at the point of service injection or lookup.
+ * Security Services, which are to protected against unqualified injection/look-up, should be annotated as something below
+ * e.g., @Secure(accessPermissionName = "security/service/<service-type>/<some-specific-name>")
+ *
+ * Any caller which injects or looks up the protected security service, the caller's jar/class should be granted the following policy
+ * e.g.,
+ * grant codeBase "file:<path>/<to>/<caller-jar>" {
+ * permission org.glassfish.security.services.common.SecureServiceAccessPermission "security/service/<service-type>/<some-specific-name>";
+ * };
+ *
+ */
+@Retention(RUNTIME)
+@Qualifier
+@Inherited
+@Target({ TYPE })
+public @interface Secure {
+
+ public static final String NAME = "accessPermissionName";
+
+ public static final String PERMISSION_NAME_PREFIX = "security/service/";
+
+ public static final String DEFAULT_PERM_NAME = PERMISSION_NAME_PREFIX + "default";
+
+ /**
+ * the permission name to be protected
+ * if the accessPermissionName is not specified, a default value of "security/service/default" is used.
+ * @return name of the protected HK2 service
+ */
+ @Metadata(NAME)
+ public String accessPermissionName();
+
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecureServiceAccessPermission.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecureServiceAccessPermission.java
new file mode 100644
index 0000000..14bdf7e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecureServiceAccessPermission.java
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.security.BasicPermission;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+
+
+public class SecureServiceAccessPermission extends BasicPermission {
+
+ private static final long serialVersionUID = -274181305911341984L;
+
+ public static final String RW_ACTION = "read,write";
+ public static final String READ_ACTION = "read";
+ public static final String WRITE_ACTION = "write";
+
+ private static final Logger _log =
+ Logger.getLogger("org.glassfish.security.services");
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(SecureServiceAccessPermission.class);
+
+ /**
+ * Read action.
+ */
+ private final static int READ = 0x1;
+
+ /**
+ * Write action.
+ */
+ private final static int WRITE = 0x2;
+ /**
+ * All actions (read,write);
+ */
+ private final static int ALL = READ|WRITE;
+
+ private final static int NONE = 0x0;
+
+ private transient int mask;
+
+ private transient boolean wildcard;
+
+ private transient String path;
+
+ private String target; //not used for now
+ private String actions; //not used for now
+
+ /**
+ *
+ * @param accessPermissionName the permission name used inside the 'Secure' annotation of the protected service
+ */
+ public SecureServiceAccessPermission(String accessPermissionName) {
+ this(accessPermissionName, null);
+ }
+
+
+ /**
+ *
+ * @param accessPermissionName the permission name used inside the 'Secure' annotation of the protected service
+ * @param actions use null (not used for now)
+ */
+ public SecureServiceAccessPermission(String accessPermissionName, String actions) {
+ super(accessPermissionName, actions);
+ this.actions = actions;
+ initWildCardPath(accessPermissionName);
+ init(getMask(actions));
+ }
+
+ /**
+ *
+ * @param accessPermissionName the permission name used inside the 'Secure' annotation of the protected service
+ * @param actions use null (not used for now)
+ * @param targetName use null (not used for now)
+ */
+ public SecureServiceAccessPermission(String accessPermissionName, String actions,
+ String targetName) {
+ this(accessPermissionName, actions);
+ this.target = targetName;
+ }
+
+ private void init(int mask)
+ {
+
+ if ((mask & ALL) != mask)
+ throw new IllegalArgumentException(
+ localStrings.getLocalString("perm.invalid.action", "invalid actions mask"));
+
+ if (getName() == null)
+ throw new NullPointerException(
+ localStrings.getLocalString("perm.null.name", "name can't be null"));
+
+ this.mask = mask;
+ }
+
+ //base on J2SE implementation
+ private static int getMask(String actions) {
+
+ int mask = NONE;
+
+ if (actions == null) {
+ return mask;
+ }
+
+ // Check against use of constants (used heavily within the JDK)
+ if (actions.equalsIgnoreCase(READ_ACTION)) {
+ return READ;
+ } if (actions.equalsIgnoreCase(WRITE_ACTION)) {
+ return WRITE;
+ } else if (actions.equalsIgnoreCase(RW_ACTION)) {
+ return READ|WRITE;
+ }
+
+ char[] a = actions.toCharArray();
+
+ int i = a.length - 1;
+ if (i < 0)
+ return mask;
+
+ while (i != -1) {
+ char c;
+
+ // skip whitespace
+ while ((i!=-1) && ((c = a[i]) == ' ' ||
+ c == '\r' ||
+ c == '\n' ||
+ c == '\f' ||
+ c == '\t'))
+ i--;
+
+ // check for the known strings
+ int matchlen;
+
+ if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') &&
+ (a[i-2] == 'e' || a[i-2] == 'E') &&
+ (a[i-1] == 'a' || a[i-1] == 'A') &&
+ (a[i] == 'd' || a[i] == 'D'))
+ {
+ matchlen = 4;
+ mask |= READ;
+
+ } else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') &&
+ (a[i-3] == 'r' || a[i-3] == 'R') &&
+ (a[i-2] == 'i' || a[i-2] == 'I') &&
+ (a[i-1] == 't' || a[i-1] == 'T') &&
+ (a[i] == 'e' || a[i] == 'E'))
+ {
+ matchlen = 5;
+ mask |= WRITE;
+
+ } else {
+ // parse error
+ throw new IllegalArgumentException(
+ localStrings.getLocalString(
+ "perm.invalid.action", "invalid actions: {0}", actions));
+ }
+
+ // make sure we didn't just match the tail of a word
+ // like "ackbarfaccept". Also, skip to the comma.
+ boolean seencomma = false;
+ while (i >= matchlen && !seencomma) {
+ switch(a[i-matchlen]) {
+ case ',':
+ seencomma = true;
+ /*FALLTHROUGH*/
+ case ' ': case '\r': case '\n':
+ case '\f': case '\t':
+ break;
+ default:
+ throw new IllegalArgumentException(
+ localStrings.getLocalString(
+ "perm.invalid.actions", "invalid actions: {0}", actions));
+ }
+ i--;
+ }
+
+ // point i at the location of the comma minus one (or -1).
+ i -= matchlen;
+ }
+
+ return mask;
+ }
+
+ @Override
+ public String getActions() {
+ return actions;
+ }
+
+ int getActionMask() {
+ return mask;
+ }
+
+
+ public String getTarget() {
+ return target;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+
+ if ((obj == null) || (obj.getClass() != getClass()))
+ return false;
+
+ SecureServiceAccessPermission sp = (SecureServiceAccessPermission)obj;
+
+ return twoStringEq(getName(), sp.getName()) &&
+ mask == sp.getActionMask() &&
+ twoStringEq(this.getTarget(), sp.getTarget());
+ }
+
+ //compare two strings
+ private static boolean twoStringEq(String s1, String s2) {
+
+ if (s1 == null && s2 == null)
+ return true;
+
+ if (s1 == null) {
+ //s2 not null, s1 is null
+ return false;
+ } else
+ //s1 not null,
+ return s1.equals(s2);
+ }
+
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+
+ @Override
+ public boolean implies(Permission p) {
+ if ((p == null) || (p.getClass() != getClass()))
+ return false;
+
+ if (!(p instanceof SecureServiceAccessPermission))
+ return false;
+
+ SecureServiceAccessPermission that = (SecureServiceAccessPermission) p;
+
+
+ boolean result = ((this.mask & that.mask) == that.mask) && nameImplies(that);
+
+ if (_log.isLoggable(Level.FINE)) {
+ _log.log(Level.FINE, "Implies for permission " + p + " return " + result);
+ }
+
+ return result;
+ }
+
+ private boolean nameImplies(SecureServiceAccessPermission that) {
+
+ if (this.wildcard) {
+ if (that.wildcard) {
+ // one wildcard can imply another
+ return that.path.startsWith(path);
+ } else {
+ // make sure ap.path is longer so a/b/* doesn't imply a/b
+ return (that.path.length() > this.path.length()) &&
+ that.path.startsWith(this.path);
+ }
+ } else {
+ if (that.wildcard) {
+ // a non-wildcard can't imply a wildcard
+ return false;
+ }
+ else {
+ return this.path.equals(that.path);
+ }
+ }
+ }
+
+
+ private void initWildCardPath(String name)
+ {
+ if (name == null)
+ throw new NullPointerException(
+ localStrings.getLocalString("perm.null.name", "name can't be null"));
+
+ int len = name.length();
+
+ if (len == 0) {
+ throw new IllegalArgumentException(
+ localStrings.getLocalString("perm.empty.name", "name can't be empty"));
+ }
+
+ char last = name.charAt(len - 1);
+
+ // Is wildcard or ends with "/*"?
+ if (last == '*' && (len == 1 || name.charAt(len - 2) == '/')) {
+ wildcard = true;
+ if (len == 1) {
+ path = "";
+ } else {
+ path = name.substring(0, len - 1);
+ }
+ } else {
+ path = name;
+ }
+ }
+
+
+ final String getCanonicalName() {
+ return getName();
+ }
+
+ public PermissionCollection newPermissionCollection() {
+ return new SecurityAccessPermissionCollection(this.getClass(), _log, localStrings);
+ }
+
+}
+
+
+
+final class SecurityAccessPermissionCollection extends PermissionCollection {
+
+ private static final long serialVersionUID = 2568719859057815986L;
+
+ /**
+ * Key is name, value is permission. All permission objects in collection
+ * must be of the same type. Not serialized; see serialization section at
+ * end of class.
+ */
+ private transient Map<String, Permission> perms;
+
+ /**
+ * This is set to <code>true</code> if this SecurityAccessPermissionCollection
+ * contains a BasicPermission with '*' as its permission name.
+ *
+ * @see #serialPersistentFields
+ */
+ private boolean all_allowed;
+
+ /**
+ * The class to which all BasicPermissions in this SecurityAccessPermissionCollection
+ * belongs.
+ *
+ * @see #serialPersistentFields
+ */
+ private Class permClass;
+
+
+ private Logger log;
+ private LocalStringManagerImpl localStrings;
+
+ public SecurityAccessPermissionCollection(Class clazz, Logger log, LocalStringManagerImpl localStrings) {
+ perms = new HashMap<String, Permission>(11);
+ all_allowed = false;
+ permClass = clazz;
+ this.log = log;
+ this.localStrings = localStrings;
+ }
+
+ /**
+ * Adds a permission to the BasicPermissions. The key for the hash is
+ * permission.path.
+ *
+ * @param permission
+ * the Permission object to add.
+ *
+ * @exception IllegalArgumentException
+ * - if the permission is not a BasicPermission, or if the
+ * permission is not of the same Class as the other
+ * permissions in this collection.
+ *
+ * @exception SecurityException
+ * - if this SecurityAccessPermissionCollection object has been marked
+ * readonly
+ */
+
+ public void add(Permission permission) {
+ if (!(permission instanceof SecureServiceAccessPermission))
+ throw new IllegalArgumentException("invalid permission: "
+ + permission);
+ if (isReadOnly())
+ throw new SecurityException(
+ localStrings.getLocalString("perm.readonly",
+ "attempt to add a Permission to a readonly PermissionCollection"));
+
+ SecureServiceAccessPermission bp = (SecureServiceAccessPermission) permission;
+
+ // make sure we only add new SecureServiceAccessPermissions of the same class
+ // Also check null for compatibility with deserialized form from
+ // previous versions.
+ if (permClass == null) {
+ // adding first permission
+ permClass = bp.getClass();
+ } else {
+ if (bp.getClass() != permClass)
+ throw new IllegalArgumentException(
+ localStrings.getLocalString(
+ "perm.invalid.perm", "invalid permission: {0}", permission));
+
+ }
+
+ synchronized (this) {
+ perms.put(bp.getCanonicalName(), permission);
+ }
+
+ // No sync on all_allowed; staleness OK
+ if (!all_allowed) {
+ if (bp.getCanonicalName().equals("*"))
+ all_allowed = true;
+ }
+ }
+
+ /**
+ * Check and see if this set of permissions implies the permissions
+ * expressed in "permission".
+ *
+ * @param p
+ * the Permission object to compare
+ *
+ * @return true if "permission" is a proper subset of a permission in the
+ * set, false if not.
+ */
+
+ public boolean implies(Permission permission) {
+ if (!(permission instanceof SecureServiceAccessPermission))
+ return false;
+
+ SecureServiceAccessPermission bp = (SecureServiceAccessPermission) permission;
+
+ // random subclasses of SecureServiceAccessPermission do not imply each other
+ if (bp.getClass() != permClass)
+ return false;
+
+ // short circuit if the "*" Permission was added
+ if (all_allowed)
+ return true;
+
+ // strategy:
+ // Check for full match first. Then work our way up the
+ // path looking for matches on a.b..*
+
+ String path = bp.getCanonicalName();
+ // System.out.println("check "+path);
+
+ Permission x;
+
+ synchronized (this) {
+ x = perms.get(path);
+ }
+
+ if (x != null) {
+ // we have a direct hit!
+ return x.implies(permission);
+ }
+
+ // work our way up the tree...
+ int last, offset;
+
+ offset = path.length() - 1;
+
+ while ((last = path.lastIndexOf("/", offset)) != -1) {
+
+ path = path.substring(0, last + 1) + "*";
+ // System.out.println("check "+path);
+
+ synchronized (this) {
+ x = perms.get(path);
+ }
+
+ if (x != null) {
+ return x.implies(permission);
+ }
+ offset = last - 1;
+ }
+
+ if (log.isLoggable(Level.FINE))
+ log.log(Level.FINE, "pemission collection returns false");
+
+ // we don't have to check for "*" as it was already checked
+ // at the top (all_allowed), so we just return false
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the SecureServiceAccessPermission objects in the
+ * container.
+ *
+ * @return an enumeration of all the SecureServiceAccessPermission objects.
+ */
+
+ public Enumeration<Permission> elements() {
+ // Convert Iterator of Map values into an Enumeration
+ synchronized (this) {
+ return Collections.enumeration(perms.values());
+ }
+ }
+
+ // Need to maintain serialization interoperability with earlier releases,
+ // which had the serializable field:
+ //
+ // @serial the Hashtable is indexed by the SecureServiceAccessPermission name
+ //
+ // private Hashtable permissions;
+ /**
+ * @serialField
+ * permissions java.util.Hashtable The SecureServiceAccessPermissions in
+ * this SecurityAccessPermissionCollection. All SecureServiceAccessPermissions in
+ * the collection must belong to the same class. The
+ * Hashtable is indexed by the SecureServiceAccessPermission name; the
+ * value of the Hashtable entry is the permission.
+ * @serialField
+ * all_allowed boolean This is set to <code>true</code> if
+ * this SecurityAccessPermissionCollection contains a
+ * SecureServiceAccessPermission with '*' as its permission name.
+ * @serialField
+ * permClass java.lang.Class The class to which all
+ * SecureServiceAccessPermissions in this SecurityAccessPermissionCollection
+ * belongs.
+ */
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("permissions", Hashtable.class),
+ new ObjectStreamField("all_allowed", Boolean.TYPE),
+ new ObjectStreamField("permClass", Class.class), };
+
+ /**
+ * @serialData Default fields.
+ */
+ /*
+ * Writes the contents of the perms field out as a Hashtable for
+ * serialization compatibility with earlier releases. all_allowed and
+ * permClass unchanged.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ // Don't call out.defaultWriteObject()
+
+ // Copy perms into a Hashtable
+ Hashtable<String, Permission> permissions =
+ new Hashtable<String, Permission>(perms.size()*2);
+
+ synchronized (this) {
+ permissions.putAll(perms);
+ }
+
+ // Write out serializable fields
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("all_allowed", all_allowed);
+ pfields.put("permissions", permissions);
+ pfields.put("permClass", permClass);
+ out.writeFields();
+ }
+
+ /**
+ * readObject is called to restore the state of the
+ * SecurityAccessPermissionCollection from a stream.
+ */
+ private void readObject(java.io.ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ // Don't call defaultReadObject()
+
+ // Read in serialized fields
+ ObjectInputStream.GetField gfields = in.readFields();
+
+ // Get permissions
+ Hashtable<String, Permission> permissions = (Hashtable<String, Permission>) gfields
+ .get("permissions", null);
+ perms = new HashMap<String, Permission>(permissions.size() * 2);
+ perms.putAll(permissions);
+
+ // Get all_allowed
+ all_allowed = gfields.get("all_allowed", false);
+
+ // Get permClass
+ permClass = (Class) gfields.get("permClass", null);
+
+ if (permClass == null) {
+ // set permClass
+ Enumeration<Permission> e = permissions.elements();
+ if (e.hasMoreElements()) {
+ Permission p = e.nextElement();
+ permClass = p.getClass();
+ }
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessFilter.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessFilter.java
new file mode 100644
index 0000000..69e2062
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessFilter.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.glassfish.hk2.api.Descriptor;
+import org.glassfish.hk2.api.Filter;
+
+public class SecurityAccessFilter implements Filter {
+
+ private static final String SYS_PROP_JAVA_SEC_POLICY = "java.security.policy";
+ private static final Logger LOG = SecurityAccessValidationService._theLog;
+
+ private static boolean javaPolicySet =
+ AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+
+ @Override
+ public Boolean run() {
+ Boolean rtn = Boolean.FALSE;
+
+ String wlsName = System.getProperty(SYS_PROP_JAVA_SEC_POLICY);
+
+ if ( wlsName != null && !wlsName.isEmpty() )
+ rtn = Boolean.TRUE;
+
+ return rtn;
+ }
+ });
+
+
+ @Override
+ public boolean matches(Descriptor d) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Descripter: " + d );
+ }
+
+ if (!javaPolicySet) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("java security policy is not set, so no validation for security servies.");
+ }
+
+ return false;
+ }
+
+ if (d == null)
+ return false;
+
+ Set<String> qualifiers = d.getQualifiers();
+ if (qualifiers != null && qualifiers.size() != 0) {
+ for (String s : qualifiers) {
+ if (Secure.class.getCanonicalName().equals(s)) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("The instance is annotated with \'Secure\': " + s);
+ }
+ return true;
+ }
+ }
+ }
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("The instance has no \'Secure\' annotated ");
+ }
+
+ return false;
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidationService.java
new file mode 100644
index 0000000..b27f6a8
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidationService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.util.logging.Logger;
+
+import javax.inject.Singleton;
+
+import org.glassfish.hk2.api.Filter;
+import org.glassfish.hk2.api.ValidationService;
+import org.glassfish.hk2.api.Validator;
+import org.jvnet.hk2.annotations.Service;
+
+
+@Service
+@Singleton
+public class SecurityAccessValidationService implements ValidationService {
+
+
+ private SecurityAccessValidator commValidator = new SecurityAccessValidator();
+
+ private SecurityAccessFilter flt = new SecurityAccessFilter();
+
+ static final Logger _theLog = Logger.getLogger("org.glassfish.security.services");
+
+
+ @Override
+ public Filter getLookupFilter() {
+ return flt;
+ }
+
+ @Override
+ public Validator getValidator() {
+ return commValidator;
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidator.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidator.java
new file mode 100644
index 0000000..4391cb8
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityAccessValidator.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.Iterator;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+
+import org.glassfish.hk2.api.ValidationInformation;
+import org.glassfish.hk2.api.Validator;
+import org.glassfish.hk2.api.ActiveDescriptor;
+import org.glassfish.hk2.api.Injectee;
+import org.glassfish.hk2.api.Descriptor;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+
+
+public class SecurityAccessValidator implements Validator {
+
+ private static final Logger LOG = SecurityAccessValidationService._theLog;
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(SecurityAccessValidator.class);
+
+
+ @Override
+ public boolean validate(ValidationInformation info) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("ValidationInformation info= " + info);
+ }
+
+ switch (info.getOperation()) {
+ case BIND:
+ case UNBIND:
+ return validateBindAndUnbind(info);
+ case LOOKUP:
+ return validateLookup(info.getCandidate(), info.getInjectee());
+ default:
+ return false;
+ }
+
+ }
+
+ private boolean isSecureAnnotated(ValidationInformation info) {
+
+ Descriptor d = info.getCandidate();
+
+ Set<String> qualifiers = d.getQualifiers();
+ if (qualifiers != null && qualifiers.size() != 0) {
+ for (String s : qualifiers) {
+ if (Secure.class.getCanonicalName().equals(s)) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("The instance is annotated with \'Secure\': "
+ + info);
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+
+ }
+
+ private boolean validateBindAndUnbind(ValidationInformation info) {
+
+ // do nothing if the instance is not annotated with 'Secure'
+ if (!isSecureAnnotated(info))
+ return true;
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("validateBindAndUnbind," + " injectee= "
+ + info.getInjectee());
+ }
+
+ return validateLookup(info.getCandidate(), info.getInjectee());
+ }
+
+ private boolean validateLookup(ActiveDescriptor<?> candidate,
+ Injectee injectee) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Lookup candiate =" + candidate + ", injectee= "
+ + injectee);
+ }
+
+ if (!candidate.isReified()) {
+ // not yet really injected yet, so not to check perm
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Lookup candiate is not reified yet");
+ }
+ return true;
+ } else {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Lookup candiate is reified, candidate = " + candidate);
+ }
+ }
+
+ Set<String> contracts = candidate.getAdvertisedContracts();
+
+ if (contracts == null)
+ return true;
+
+ Map<String, List<String>> md = candidate.getMetadata();
+
+ if (LOG.isLoggable(Level.FINE)) {
+ Iterator<Map.Entry<String, List<String>>> itr = md.entrySet().iterator();
+ while (itr.hasNext()) {
+ Map.Entry<String, List<String>> entry = itr.next();
+ String k = entry.getKey();
+ for (String v : entry.getValue()) {
+ LOG.fine("$$ key= " + k + ", value= " + v);
+ }
+ }
+ }
+
+ Permission perm = null;
+ List<String> names = md.get(Secure.NAME);
+ if (names == null || names.isEmpty()) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Perm name is empty, will use default value");
+ }
+
+ //the 'Secure' annotation did not specify a accessPermissionName, use default accessPermissionName name
+ perm = getAccessPermision(Secure.DEFAULT_PERM_NAME, null);
+
+ } else {
+ String permName = names.get(0);
+ perm = getAccessPermision(permName, null);
+ }
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("The permission to be protected = " + perm);
+ }
+
+ boolean check_result = false;
+ if (injectee == null) {
+ // lookup style check
+
+ Class caller = getServiceLookupCaller();
+
+ check_result = checkPerm(perm, caller);
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Lookup, checked perm for = " + perm + ", result= "
+ + check_result);
+ }
+ } else {
+ // injection style check
+ check_result = validateInjection(candidate, injectee, perm);
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Injection, checked perm for = " + perm + ", result= "
+ + check_result);
+ }
+ }
+
+ return check_result;
+ }
+
+
+ //temporary alternative fixing to JIRA-HK2:116
+ private Class getServiceLookupCaller() {
+/*
+ StackTraceElement[] steArr = new Exception().getStackTrace();
+
+ for (int i = 0; i < steArr.length; i++ ) {
+ StackTraceElement elm = steArr[i];
+
+ if (elm.getClassName().equals("org.jvnet.hk2.internal.ServiceLocatorImpl") &&
+ (elm.getMethodName().equals("getService") ||
+ elm.getMethodName().equals("getAllServices") ||
+ elm.getMethodName().equals("getServiceHandle") ||
+ elm.getMethodName().equals("getAllServiceHandles") ||
+ elm.getMethodName().equals("create") ||
+ elm.getMethodName().equals("createAndInitialize") ||
+ elm.getMethodName().equals("shutdown")
+
+ )) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Found the service locator, classname= "
+ + steArr[i+1].getClassName() + ", ste =" + steArr[i+1]);
+ }
+
+ //after finding the 1st service locator, then look for the class which is not ServiceLocatorImpl
+ System.out.println("%%%%found the locator");
+ for (int j = i+1; j < steArr.length; j++ ) {
+ StackTraceElement elmj = steArr[j];
+ if (elmj.getClassName().startsWith("org.jvnet.hk2.internal.")) //by pass all hk2 classes to find the caller
+ continue;
+ else {
+ StackTraceElement caller = elmj;
+ //found the caller class which is not ServiceLocatorImpl
+ System.out.println("%%%caller Class name= " + caller.getClassName() + ", caller ste =" + caller +
+ ", method=" + caller.getMethodName());
+ try {
+ return Class.forName(caller.getClassName(), true, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+
+ try {
+ return Class.forName(caller.getClassName());
+ } catch (ClassNotFoundException e1) {
+ // TODO Auto-generated catch block
+ //e1.printStackTrace();
+ LOG.warning(localStrings.getLocalString("sec.validate.lookup.noclass",
+ "Lookup Class not found in classpath: {0}", caller.getClassName()));
+ throw new RuntimeException(e);
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ System.out.println("%%%caller Class= null");
+ LOG.warning(localStrings.getLocalString("sec.validate.lookup.fail", "Cannot find the looup caller class"));
+*/
+ return null;
+
+ }
+
+ private boolean checkPerm(Permission p, Class caller) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Checked perm for = " + p);
+ }
+
+
+ try {
+ if (caller != null) {
+ ProtectionDomain pd = this.getCallerProtDomain(caller);
+ pd.implies(p);
+ } else
+ AccessController.checkPermission(p);
+
+ } catch (SecurityException e) {
+
+ LOG.warning(localStrings.getLocalString(
+ "sec.validate.lookup.deny", "Check Permission failed in lookup for permission = {0}", p));
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Check Permission failed, perm= " + p + ", message = "
+ + e.getMessage());
+ }
+ throw e;
+ }
+
+ return true;
+ }
+
+
+ private boolean validateInjection(ActiveDescriptor<?> candidate,
+ Injectee injectee, Permission p) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Injectee =" + injectee + ", permission= " + p);
+ }
+
+ // If this is an Inject, get the protection domain of the injectee
+ Class<?> injecteeClass = injectee.getInjecteeClass();
+
+ ProtectionDomain pd = getCallerProtDomain(injecteeClass);
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Protection domain code src= " + pd.getCodeSource());
+ }
+
+ if (!pd.implies(p)) {
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("permission check failed for " + injectee + ", to get perm " + p + ", for candidate "
+ + candidate);
+ }
+
+ throw new AccessControlException(localStrings.getLocalString("sec.validate.injection.deny",
+ "Access denied for injectee {0} to get permission {1}.", injectee, p));
+
+ } else {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("permission check success for " + injectee
+ + " to get " + candidate);
+ }
+ }
+
+ return true;
+ }
+
+ private ProtectionDomain getCallerProtDomain(final Class caller) {
+ ProtectionDomain pd = AccessController
+ .doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+ @Override
+ public ProtectionDomain run() {
+ return caller.getProtectionDomain();
+ }
+ });
+
+ return pd;
+ }
+
+
+ /**
+ * The permission to be checked
+ *
+ * @return permission to be checked
+ */
+ private Permission getAccessPermision(String protectName, String action) {
+ return new SecureServiceAccessPermission(protectName, action);
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScope.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScope.java
new file mode 100644
index 0000000..df67c82
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScope.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import javax.inject.Scope;
+
+import org.glassfish.hk2.api.Proxiable;
+
+/**
+ * Scope used by security services that enables a flexible binding to service instances.
+ */
+@Retention(RUNTIME)
+@Scope
+// @Proxiable MUST be added back in later once we understand why cglib is having problems
+@Target({ TYPE, METHOD })
+public @interface SecurityScope {
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScopeContext.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScopeContext.java
new file mode 100644
index 0000000..722ec14
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SecurityScopeContext.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.hk2.api.ActiveDescriptor;
+import org.glassfish.hk2.api.Context;
+import org.glassfish.hk2.api.ServiceHandle;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * The security context used to enable the scoping of security service instances.
+ */
+@Service
+@Singleton
+public class SecurityScopeContext implements Context<SecurityScope> {
+ private final HashMap<String, HashMap<ActiveDescriptor<?>, Object>> contexts =
+ new HashMap<String, HashMap<ActiveDescriptor<?>, Object>>();
+
+ @Inject
+ private StateManager manager;
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return SecurityScope.class;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T findOrCreate(ActiveDescriptor<T> activeDescriptor, ServiceHandle<?> root) {
+ HashMap<ActiveDescriptor<?>, Object> mappings = getCurrentContext();
+
+ Object retVal = mappings.get(activeDescriptor);
+ if (retVal == null) {
+ retVal = activeDescriptor.create(root);
+
+ mappings.put(activeDescriptor, retVal);
+ }
+ return (T) retVal;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsKey(ActiveDescriptor<?> descriptor) {
+ HashMap<ActiveDescriptor<?>, Object> mappings = getCurrentContext();
+
+ return mappings.containsKey(descriptor);
+ }
+
+ @Override
+ public boolean isActive() {
+ return manager.getCurrent() != null;
+ }
+
+ private HashMap<ActiveDescriptor<?>, Object> getCurrentContext() {
+ if (manager.getCurrent() == null) throw new IllegalStateException("Not In Active State");
+
+ HashMap<ActiveDescriptor<?>, Object> retVal = contexts.get(manager.getCurrent());
+ if (retVal == null) {
+ retVal = new HashMap<ActiveDescriptor<?>, Object>();
+
+ contexts.put(manager.getCurrent(), retVal);
+ }
+
+ return retVal;
+ }
+
+ /* (non-Javadoc)
+ * @see org.glassfish.hk2.api.Context#supportsNullCreation()
+ */
+ @Override
+ public boolean supportsNullCreation() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.glassfish.hk2.api.Context#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ // Do nothing
+
+ }
+
+ @Override
+ public void destroyOne(ActiveDescriptor<?> descriptor) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/StateManager.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/StateManager.java
new file mode 100644
index 0000000..7f11326
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/StateManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import javax.inject.Singleton;
+
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * The StateManager determines the security service instance selection.
+ */
+@Service
+@Singleton
+public class StateManager {
+ // private String current;
+ private String current = "default";
+
+ public void setCurrent(String current) {
+ this.current = current;
+ }
+
+ public String getCurrent() {
+ return current;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SubjectUtil.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SubjectUtil.java
new file mode 100644
index 0000000..dc232eb
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/common/SubjectUtil.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+import javax.security.auth.Subject;
+import java.security.Principal;
+
+import org.glassfish.security.common.PrincipalImpl;
+import org.glassfish.security.common.Group;
+
+public class SubjectUtil {
+
+ /**
+ * Utility method to find the user names from a subject. The method assumes the user name is
+ * represented by {@link org.glassfish.security.common.PrincipalImpl PrincipalImpl } inside the Subject's principal set.
+ * @param subject the subject from which to find the user name
+ * @return a list of strings representing the user name. The list may have more than one entry if the subject's principal set
+ * contains more than one PrincipalImpl instances, or empty entry (i.e., anonymous user) if the subject's principal set contains no PrincipalImpl instances.
+ */
+ public static List<String> getUsernamesFromSubject(Subject subject) {
+
+ List<String> userList = new ArrayList<String>();
+
+ Set<Principal> princSet = null;
+
+ if (subject != null) {
+
+ princSet = subject.getPrincipals();
+ for (Principal p : princSet) {
+ if ((p != null) && (
+ p.getClass().isAssignableFrom(PrincipalImpl.class) ||
+ "weblogic.security.principal.WLSUserImpl".equals(p.getClass().getCanonicalName())
+ )) {
+ String uName = p.getName();
+ userList.add(uName);
+ }
+ }
+ }
+
+ return userList;
+ }
+
+
+ /**
+ * Utility method to find the group names from a subject. The method assumes the group name is
+ * represented by {@link org.glassfish.security.common.Group Group } inside the Subject's principal set.
+ * @param subject the subject from which to find the username
+ * @return a list of strings representing the group names. The list may have more than one entry if the subject's principal set
+ * contains more than one Group instances, or empty entry if the subject's principal set contains no Group instances.
+ */
+ public static List<String> getGroupnamesFromSubject(Subject subject) {
+
+ List<String> groupList = new ArrayList<String>();
+
+ Set<Group> princSet = null;
+
+ if (subject != null) {
+
+ princSet = subject.getPrincipals(Group.class);
+ for (PrincipalImpl g : princSet) {
+ String gName = g.getName();
+ groupList.add(gName);
+ }
+ }
+
+ return groupList;
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthenticationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthenticationService.java
new file mode 100644
index 0000000..809fc00
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthenticationService.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import java.beans.PropertyVetoException;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+
+/**
+ * The AuthenticationService Configuration
+ */
+@Configured
+public interface AuthenticationService extends SecurityConfiguration {
+ /**
+ * Determines if the Authentication Service instance should use
+ * a GlassFish AuthRealm PasswordCredential with the LoginModule(s).
+ */
+ @Attribute(defaultValue = "false")
+ boolean getUsePasswordCredential();
+ void setUsePasswordCredential(boolean value) throws PropertyVetoException;
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthorizationService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthorizationService.java
new file mode 100644
index 0000000..7ec7571
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/AuthorizationService.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+
+import org.jvnet.hk2.config.Configured;
+
+
+@Configured
+public interface AuthorizationService extends SecurityConfiguration {
+
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/LoginModuleConfig.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/LoginModuleConfig.java
new file mode 100644
index 0000000..3cdb9c1
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/LoginModuleConfig.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.DuckTyped;
+import org.jvnet.hk2.config.Element;
+import org.jvnet.hk2.config.types.Property;
+import org.jvnet.hk2.config.types.PropertyBag;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.beans.PropertyVetoException;
+import javax.validation.constraints.NotNull;
+import com.sun.enterprise.config.serverbeans.customvalidators.JavaClassName;
+
+/**
+ * The LoginModule configuration used for a security provider plugin.
+ *
+ * Defines setup for standard JAAS LoginModule Configuration.
+ */
+@Configured
+public interface LoginModuleConfig extends SecurityProviderConfig, PropertyBag {
+ /**
+ * Gets the class name of the LoginModule.
+ */
+ @Attribute(required=true)
+ @NotNull
+ @JavaClassName
+ public String getModuleClass();
+ public void setModuleClass(String value) throws PropertyVetoException;
+
+ /**
+ * Gets the JAAS control flag of the LoginModule.
+ */
+ @Attribute(required=true)
+ @NotNull
+ public String getControlFlag();
+ public void setControlFlag(String value) throws PropertyVetoException;
+
+ /**
+ * Gets the properties of the LoginModule.
+ */
+ @Element
+ List<Property> getProperty();
+
+ /**
+ * Gets the options of the LoginModule for use with JAAS Configuration.
+ */
+ @DuckTyped
+ Map<String,?> getModuleOptions();
+
+ class Duck {
+ /**
+ * Gets the options of the LoginModule for use with JAAS Configuration.
+ */
+ public static Map<String,?> getModuleOptions(LoginModuleConfig config) {
+ Map<String,String> moduleOptions = new HashMap<String,String>();
+ for (Property prop : config.getProperty()) {
+ moduleOptions.put(prop.getName(), prop.getValue());
+ }
+ return moduleOptions;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/RoleMappingService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/RoleMappingService.java
new file mode 100644
index 0000000..f7c950e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/RoleMappingService.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import org.jvnet.hk2.config.Configured;
+
+@Configured
+public interface RoleMappingService extends SecurityConfiguration {
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigUpgradeService.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigUpgradeService.java
new file mode 100644
index 0000000..0ebd0c5
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigUpgradeService.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.auth.login.FileLoginModule;
+import org.glassfish.api.admin.config.ConfigurationUpgrade;
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.security.services.provider.authorization.AuthorizationProviderConfig;
+import org.jvnet.hk2.annotations.Service;
+import org.jvnet.hk2.config.Transaction;
+import org.jvnet.hk2.config.TransactionFailure;
+import org.jvnet.hk2.config.types.Property;
+
+import javax.inject.Inject;
+import java.beans.PropertyVetoException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Upgrades the configuration to use the default file realm and the
+ * login module which handles non-username/password admin authentication.
+ *
+ * @author tjquinn
+ * @author Masoud Kalali
+ */
+@Service
+@PerLookup
+public class SecurityConfigUpgradeService implements ConfigurationUpgrade, PostConstruct {
+
+ private static final String AUTHENTICATION_SERVICE_NAME = "adminAuth";
+ private static final String FILE_REALM_PROVIDER_NAME = "filerealm";
+ private static final String FILE_REALM_PROVIDER_PROVIDER_NAME = "adminFile";
+ private static final String FILE_LOGIN_MODULE_NAME = "adminFileLM";
+ private static final String FILE_LOGIN_MODULE_CLASS = FileLoginModule.class.getName();
+
+ private static final String ADM_REALM_PROVIDER_NAME = "spcrealm";
+ private static final String ADM_REALM_PROVIDER_PROVIDER_NAME = "adminSpc";
+ private static final String ADM_LOGIN_MODULE_NAME = "adminSpecialLM";
+ private static final String ADM_LOGIN_MODULE_CLASS = "com.sun.enterprise.admin.util.AdminLoginModule";
+
+ private static final String LOGIN_MODULE_TYPE_NAME = "LoginModule";
+
+ private static final String AUTHORIZATION_SERVICE_NAME = "authorizationService";
+ private static final String SIMPLE_PROVIDER_PROVIDER_NAME = "simpleAuthorizationProvider";
+ private static final String SIMPLE_PROVIDER_NAME = "simpleAuthorization";
+ private static final String SIMPLE_PROVIDER_TYPE = "simple";
+ private static final String SIMPLE_PROVIDER_CONFIG_NAME = "simpleAuthorizationProviderConfig";
+ private static final String SIMPLE_PROVIDER_CLASS_NAME = "org.glassfish.security.services.provider.authorization.SimpleAuthorizationProviderImpl";
+ private static final String SUPPORT_POLICY_DEPLOY = "false";
+
+ private static final Logger logger = Logger.getAnonymousLogger();
+
+ @Inject
+ private Domain domain;
+
+ @Override
+ public void postConstruct() {
+ if (domain.getExtensionByType(SecurityConfigurations.class) != null) {
+ /*
+ * The domain already contains a security-configurations setting,
+ * so for now that's sufficient to conclude we don't need to upgrade.
+ */
+ logger.log(Level.INFO, "SecurityConfigUpgradeService bypassing - security-configurations already present");
+ return;
+ }
+ Transaction t = null;
+ try {
+ t = new Transaction();
+ final Domain domain_w = t.enroll(domain);
+
+ /*
+ * Create the security configurations element and add it to the domain.
+ */
+ final SecurityConfigurations sc_w = domain_w.createChild(SecurityConfigurations.class);
+ domain_w.getExtensions().add(sc_w);
+
+ /*
+ * Create and add the authentication service.
+ */
+ final AuthenticationService as_w = addAuthenticationService(sc_w);
+
+ /*
+ * Next, add the two providers and their children.
+ */
+ addAdmRealmProvider(as_w);
+ addFileRealmProvider(as_w);
+
+ /**
+ * Next add the authorization service
+ */
+ final AuthorizationService authorizationService = addAuthorizationService(sc_w);
+ /**
+ * Next add the authorization service provider
+ */
+ addSimpleAuthorizationProvider(authorizationService);
+
+ t.commit();
+ logger.log(Level.INFO, "SecurityConfigUpgradeService successfully completed the upgrade");
+
+ } catch (Exception ex) {
+ if (t != null) {
+ t.rollback();
+ }
+ logger.log(Level.SEVERE, null, ex);
+ }
+ }
+
+ private AuthenticationService addAuthenticationService(final SecurityConfigurations sc_w) throws TransactionFailure, PropertyVetoException {
+ final AuthenticationService as_w = sc_w.createChild(AuthenticationService.class);
+ sc_w.getSecurityServices().add(as_w);
+ as_w.setDefault(true);
+ as_w.setName(AUTHENTICATION_SERVICE_NAME);
+ as_w.setUsePasswordCredential(true);
+ return as_w;
+ }
+
+ private SecurityProvider addFileRealmProvider(final AuthenticationService as_w) throws PropertyVetoException, TransactionFailure {
+ final SecurityProvider sp_w = addProvider(as_w, FILE_REALM_PROVIDER_NAME, FILE_REALM_PROVIDER_PROVIDER_NAME, LOGIN_MODULE_TYPE_NAME);
+ addLoginModule(sp_w, FILE_LOGIN_MODULE_NAME, FILE_LOGIN_MODULE_CLASS);
+ return sp_w;
+
+ }
+
+ private SecurityProvider addAdmRealmProvider(final AuthenticationService as_w) throws TransactionFailure, PropertyVetoException {
+ final SecurityProvider sp_w = addProvider(as_w, ADM_REALM_PROVIDER_NAME, ADM_REALM_PROVIDER_PROVIDER_NAME, LOGIN_MODULE_TYPE_NAME);
+ addLoginModule(sp_w, ADM_LOGIN_MODULE_NAME, ADM_LOGIN_MODULE_CLASS);
+ return sp_w;
+ }
+
+ private SecurityProvider addProvider(final AuthenticationService as_w, final String providerName, final String providerProviderName,
+ final String type) throws TransactionFailure, PropertyVetoException {
+
+ final SecurityProvider sp_w = as_w.createChild(SecurityProvider.class);
+ as_w.getSecurityProviders().add(sp_w);
+ sp_w.setName(providerName);
+ sp_w.setProviderName(providerProviderName);
+ sp_w.setType(type);
+ return sp_w;
+ }
+
+ private LoginModuleConfig addLoginModule(final SecurityProvider sp_w, final String name, final String className) throws TransactionFailure, PropertyVetoException {
+ final LoginModuleConfig lm_w = sp_w.createChild(LoginModuleConfig.class);
+ sp_w.getSecurityProviderConfig().add(lm_w);
+ lm_w.setName(name);
+ lm_w.setModuleClass(className);
+ lm_w.setControlFlag("sufficient");
+
+ final Property configProp = lm_w.createChild(Property.class);
+ configProp.setName("config");
+ configProp.setValue("server-config");
+
+ final Property realmProp = lm_w.createChild(Property.class);
+ realmProp.setName("auth-realm");
+ realmProp.setValue("admin-realm");
+
+ lm_w.getProperty().add(configProp);
+ lm_w.getProperty().add(realmProp);
+ return lm_w;
+
+ }
+
+ private AuthorizationService addAuthorizationService(final SecurityConfigurations sc_w) throws TransactionFailure, PropertyVetoException {
+ final AuthorizationService as_w = sc_w.createChild(AuthorizationService.class);
+ sc_w.getSecurityServices().add(as_w);
+ as_w.setDefault(true);
+ as_w.setName(AUTHORIZATION_SERVICE_NAME);
+ return as_w;
+ }
+
+ private SecurityProvider addSimpleAuthorizationProvider(final AuthorizationService as_w) throws PropertyVetoException, TransactionFailure {
+ final SecurityProvider sp_w = addAuthzProvider(as_w, SIMPLE_PROVIDER_NAME, SIMPLE_PROVIDER_PROVIDER_NAME, SIMPLE_PROVIDER_TYPE);
+ addAuthorizationConfig(sp_w, SIMPLE_PROVIDER_CONFIG_NAME, SUPPORT_POLICY_DEPLOY);
+ return sp_w;
+ }
+
+ private void addAuthorizationConfig(SecurityProvider sp_w, String configName, String supportPolicyDeploy) throws TransactionFailure, PropertyVetoException {
+ final AuthorizationProviderConfig authorizationProviderConfig = sp_w.createChild(AuthorizationProviderConfig.class);
+ authorizationProviderConfig.setName(configName);
+ authorizationProviderConfig.setSupportPolicyDeploy(Boolean.valueOf(supportPolicyDeploy));
+ authorizationProviderConfig.setProviderClass(SIMPLE_PROVIDER_CLASS_NAME);
+ sp_w.getSecurityProviderConfig().add(authorizationProviderConfig);
+ }
+
+ private SecurityProvider addAuthzProvider(AuthorizationService as_w, String simpleProviderName, String simpleProviderProviderName, String simpleProviderType) throws TransactionFailure, PropertyVetoException {
+ final SecurityProvider sp_w = as_w.createChild(SecurityProvider.class);
+ sp_w.setName(simpleProviderName);
+ sp_w.setProviderName(simpleProviderProviderName);
+ sp_w.setType(simpleProviderType);
+ as_w.getSecurityProviders().add(sp_w);
+ return sp_w;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfiguration.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfiguration.java
new file mode 100644
index 0000000..6540b50
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfiguration.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.ConfigBeanProxy;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.DuckTyped;
+import org.jvnet.hk2.config.Element;
+
+import javax.validation.constraints.NotNull;
+import java.beans.PropertyVetoException;
+import java.util.List;
+
+/**
+ * Base interface for all security service configurations.
+ *
+ * Each security service configuration has a name, indication of the service
+ * configuration being the default when multiple service configurations are
+ * present and an optional list of the specific security provider plugins.
+ */
+@Configured
+public interface SecurityConfiguration extends ConfigBeanProxy {
+ /**
+ * Gets the name of the security service instance.
+ */
+ @Attribute(required=true, key=true)
+ @NotNull
+ public String getName();
+ public void setName(String value) throws PropertyVetoException;
+
+ /**
+ * Determine if this is the default instance.
+ */
+ @Attribute(defaultValue = "false")
+ boolean getDefault();
+ void setDefault(boolean defaultValue) throws PropertyVetoException;
+
+ /**
+ * Gets the list of the security provider plugins used by the security service.
+ */
+ @Element("security-provider")
+ List<SecurityProvider> getSecurityProviders();
+
+ /**
+ * Gets a named security provider.
+ */
+ @DuckTyped
+ SecurityProvider getSecurityProviderByName(String name);
+
+ class Duck {
+ /**
+ * Gets a named security provider.
+ */
+ public static SecurityProvider getSecurityProviderByName(SecurityConfiguration securityServiceConfiguration, String name) {
+ for (SecurityProvider config : securityServiceConfiguration.getSecurityProviders()) {
+ if (config.getProviderName().equals(name)) {
+ return config;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigurations.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigurations.java
new file mode 100644
index 0000000..83d8ee4
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityConfigurations.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import com.sun.enterprise.config.serverbeans.DomainExtension;
+import com.sun.enterprise.config.modularity.annotation.HasNoDefaultConfiguration;
+import org.jvnet.hk2.config.ConfigBeanProxy;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.DuckTyped;
+import org.jvnet.hk2.config.Element;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * The top level security configuration which holds the list of configured security services.
+ */
+@Configured
+@HasNoDefaultConfiguration
+public interface SecurityConfigurations extends ConfigBeanProxy, DomainExtension {
+ /**
+ * Gets the list of configured security services.
+ */
+ @Element("*")
+ List<SecurityConfiguration> getSecurityServices();
+
+ /**
+ * Gets the list of configured security services by security service type.
+ */
+ @DuckTyped
+ <T extends SecurityConfiguration> List<T> getSecurityServicesByType(Class<T> type);
+
+ /**
+ * Gets the default configured security service by security service type.
+ */
+ @DuckTyped
+ <T extends SecurityConfiguration> T getDefaultSecurityServiceByType(Class<T> type);
+
+ /**
+ * Gets a named security service configuration by specific security type.
+ */
+ @DuckTyped
+ <T extends SecurityConfiguration> T getSecurityServiceByName(String name, Class<T> type);
+
+ /**
+ * Gets a named security service configuration.
+ */
+ @DuckTyped
+ SecurityConfiguration getSecurityServiceByName(String name);
+
+ class Duck {
+ /**
+ * Gets the list of configured security services by security service type.
+ */
+ public static <T extends SecurityConfiguration> List<T> getSecurityServicesByType(SecurityConfigurations services, Class<T> type) {
+ List<T> typedServices = new ArrayList<T>();
+ for (SecurityConfiguration securityServiceConfiguration : services.getSecurityServices()) {
+ try {
+ if (type.isAssignableFrom(securityServiceConfiguration.getClass())) {
+ typedServices.add(type.cast(securityServiceConfiguration));
+ }
+ } catch (Exception e) {
+ // ignore, not the right type.
+ }
+ }
+ return Collections.unmodifiableList(typedServices);
+ }
+
+ /**
+ * Gets the default configured security service by security service type.
+ */
+ public static <T extends SecurityConfiguration> T getDefaultSecurityServiceByType(SecurityConfigurations services, Class<T> type) {
+ for (SecurityConfiguration securityServiceConfiguration : services.getSecurityServices()) {
+ try {
+ if (securityServiceConfiguration.getDefault()) {
+ return type.cast(securityServiceConfiguration);
+ }
+ } catch (Exception e) {
+ // ignore, not the right type.
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets a named security service configuration by specific security type.
+ */
+ public static <T extends SecurityConfiguration> T getSecurityServiceByName(SecurityConfigurations services, String name, Class<T> type) {
+ for (SecurityConfiguration securityServiceConfiguration : services.getSecurityServices()) {
+ try {
+ if (securityServiceConfiguration.getName().equals(name)) {
+ return type.cast(securityServiceConfiguration);
+ }
+ } catch (Exception e) {
+ // ignore, not the right type.
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets a named security service configuration.
+ */
+ public static SecurityConfiguration getSecurityServiceByName(SecurityConfigurations services, String name) {
+ for (SecurityConfiguration securityServiceConfiguration : services.getSecurityServices()) {
+ if (securityServiceConfiguration.getName().equals(name)) {
+ return securityServiceConfiguration;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProvider.java
new file mode 100644
index 0000000..dbb4a9e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import java.util.List;
+
+import java.beans.PropertyVetoException;
+import javax.validation.constraints.NotNull;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.ConfigBeanProxy;
+import org.jvnet.hk2.config.Element;
+
+/**
+ * The configuration that is used by a security service to identify the
+ * set of security providers which are created and consumed by the service.
+ */
+@Configured
+public interface SecurityProvider extends ConfigBeanProxy {
+ /**
+ * Gets the name of the security provider.
+ * The name represents the qualifier @Named given to the security provider.
+ */
+ @Attribute
+ @NotNull
+ public String getName();
+ public void setName(String value) throws PropertyVetoException;
+
+ /**
+ * Gets the type of the security provider.
+ * The type represents a String used by the security service for the security provider interface.
+ */
+ @Attribute(required=true)
+ @NotNull
+ String getType();
+ void setType(String type) throws PropertyVetoException;
+
+ /**
+ * Gets the name of the security provider configuration instance.
+ * The provider name is used to reference specific provider configuration objects.
+ */
+ @Attribute(required=true, key=true)
+ @NotNull
+ String getProviderName();
+ void setProviderName(String name) throws PropertyVetoException;
+
+ /**
+ * Gets configuration object specific to the security provider implementation.
+ * Security provider configuration must extend the SecurityProviderConfig interface.
+ */
+ @Element("*")
+ List<SecurityProviderConfig> getSecurityProviderConfig();
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProviderConfig.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProviderConfig.java
new file mode 100644
index 0000000..f1be06b
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/config/SecurityProviderConfig.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.config;
+
+import java.beans.PropertyVetoException;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.ConfigBeanProxy;
+
+/**
+ * Base interface for all security provider implementation configuration.
+ *
+ * Security plugin configuration objects extend SecurityProviderConfig interface
+ * such that the configuration of the plugin can be associated with a specific
+ * security service configuration.
+ */
+@Configured
+public interface SecurityProviderConfig extends ConfigBeanProxy {
+ /**
+ * Gets the name of the security provider implementation.
+ */
+ @Attribute(required=true, key=true)
+ public String getName();
+ public void setName(String value) throws PropertyVetoException;
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceFactory.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceFactory.java
new file mode 100644
index 0000000..c8de27b
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceFactory.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import java.security.AccessController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.glassfish.hk2.api.Factory;
+import org.glassfish.hk2.api.ServiceLocator;
+
+import org.glassfish.security.services.common.PrivilegedLookup;
+import org.glassfish.security.services.common.Secure;
+import org.glassfish.security.services.common.StateManager;
+import org.glassfish.security.services.common.SecurityScope;
+
+import org.glassfish.security.services.api.authentication.AuthenticationService;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+
+/**
+ * The factory of AuthenticationService instances used by the SecurityScopeContext.
+ */
+@Singleton
+@Secure(accessPermissionName = "security/service/authentication")
+public class AuthenticationServiceFactory extends ServiceFactory implements Factory<AuthenticationService> {
+
+ @Inject
+ private StateManager manager;
+
+ @Inject
+ private ServiceLocator serviceLocator;
+
+ @SecurityScope
+ public AuthenticationService provide() {
+ String currentState = manager.getCurrent();
+
+ // Get Service Instance
+ AuthenticationService atnService = AccessController.doPrivileged(
+ new PrivilegedLookup<AuthenticationService>(
+ serviceLocator, AuthenticationService.class));
+
+ // Get Service Configuration
+ org.glassfish.security.services.config.AuthenticationService atnConfiguration =
+ serviceLocator.getService(org.glassfish.security.services.config.AuthenticationService.class,currentState);
+
+ // Initialize Service
+ atnService.initialize(atnConfiguration);
+
+ return atnService;
+ }
+
+ @Override
+ public void dispose(AuthenticationService instance) {
+ }
+
+ /**
+ * Helper function to obtain the Authentication Service configuration from the Domain.
+ */
+ public static org.glassfish.security.services.config.AuthenticationService getAuthenticationServiceConfiguration(Domain domain) {
+ org.glassfish.security.services.config.AuthenticationService atnConfiguration =
+ ServiceFactory.getSecurityServiceConfiguration(
+ domain, org.glassfish.security.services.config.AuthenticationService.class);
+ return atnConfiguration;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceImpl.java
new file mode 100644
index 0000000..b5ea778
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/AuthenticationServiceImpl.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import java.io.IOException;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.api.Globals;
+import org.glassfish.internal.api.ServerContext;
+import org.glassfish.security.services.api.authentication.AuthenticationService;
+import org.glassfish.security.services.api.authentication.ImpersonationService;
+import org.glassfish.security.services.config.LoginModuleConfig;
+import org.glassfish.security.services.config.SecurityConfiguration;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.config.SecurityProviderConfig;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.security.services.common.Secure;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import com.sun.enterprise.security.auth.realm.RealmsManager;
+import com.sun.enterprise.security.common.AppservAccessController;
+
+/**
+ * The Authentication Service Implementation.
+ *
+ * Use JAAS LoginContext with the LoginModule(s) specified by the service configuration.
+ */
+@Service
+@Singleton
+@Secure(accessPermissionName = "security/service/authentication")
+public class AuthenticationServiceImpl implements AuthenticationService, PostConstruct {
+ @Inject
+ private Domain domain;
+
+ @Inject
+ ServerContext serverContext;
+
+ @Inject
+ private ServiceLocator locator;
+
+ @Inject
+ private ImpersonationService impersonationService;
+
+ private static final Logger LOG = Logger.getLogger(AuthenticationServiceImpl.class.getName());
+
+
+ // Authentication Service Configuration Information
+ private String name = null;
+ private String realmName = null;
+ private Configuration configuration = null;
+ private boolean usePasswordCredential = false;
+ private org.glassfish.security.services.config.AuthenticationService config = null;
+
+
+ /**
+ * Initialize the Authentication Service configuration.
+ *
+ * Create the JAAS Configuration using the specified LoginModule configurations
+ */
+ @Override
+ public void initialize(SecurityConfiguration securityServiceConfiguration) {
+// org.glassfish.security.services.config.AuthenticationService as = (org.glassfish.security.services.config.AuthenticationService) securityServiceConfiguration;
+// LOG.info("*** AuthenticationServiceImpl auth svc file realm provider module class: ");
+// for (SecurityProvider sp : as.getSecurityProviders()) {
+// LOG.info(" *** Provider name/type" + sp.getName() + "/" + sp.getType());
+// if (sp.getSecurityProviderConfig() == null) {
+// LOG.info(" *** getSecurityProviderConfig returned null");
+// } else {
+// for (SecurityProviderConfig spc : sp.getSecurityProviderConfig()) {
+// LOG.info(" *** " + spc.getName());
+// if (sp.getType().equals("LoginModule")) {
+// LoginModuleConfig lmc = (LoginModuleConfig) spc;
+// LOG.info(" *** LoginModule config: class is " + lmc.getModuleClass());
+// }
+// }
+// }
+// }
+ config = (org.glassfish.security.services.config.AuthenticationService) securityServiceConfiguration;
+ if (config == null)
+ return;
+
+ // JAAS LoginContext Name
+ name = config.getName();
+
+ // Determine if handling Realm password credential
+ usePasswordCredential = config.getUsePasswordCredential();
+
+ // Build JAAS Configuration based on the individual LoginModuleConfig settings
+ List<SecurityProvider> providers = config.getSecurityProviders();
+ if (providers != null) {
+ ArrayList<AppConfigurationEntry> lmEntries = new ArrayList<AppConfigurationEntry>();
+ for (SecurityProvider provider : providers) {
+
+ // If the provider is a LoginModule look for the LoginModuleConfig
+ if ("LoginModule".equalsIgnoreCase(provider.getType())) {
+ List<SecurityProviderConfig> providerConfig = provider.getSecurityProviderConfig();
+ if ((providerConfig != null) && (!providerConfig.isEmpty())) {
+
+ // Create the JAAS AppConfigurationEntry from the LoginModule settings
+ LoginModuleConfig lmConfig = (LoginModuleConfig) providerConfig.get(0);
+ Map<String, ?> lmOptions = lmConfig.getModuleOptions();
+ lmEntries.add(new AppConfigurationEntry(lmConfig.getModuleClass(),
+ getLoginModuleControlFlag(lmConfig.getControlFlag()),lmOptions));
+
+ // Obtain the Realm name for password credential from the LoginModule options
+ // Use the first LoginModule with auth-realm (i.e. unable to stack Realms)
+ if (usePasswordCredential && (realmName == null)) {
+ String authRealm = (String) lmOptions.get("auth-realm");
+ if ((authRealm != null) && (!authRealm.isEmpty()))
+ realmName = authRealm;
+ }
+ }
+ }
+ }
+ if (!lmEntries.isEmpty())
+ configuration = new AuthenticationJaasConfiguration(name,lmEntries);
+ }
+
+ // If required, initialize the currently configured Realm instances
+ // TODO - Reconcile initialization with SecurityLifeCycle
+ if (usePasswordCredential && (realmName != null)) {
+ RealmsManager realmsManager = locator.getService(RealmsManager.class);
+ realmsManager.createRealms();
+ }
+ }
+
+ @Override
+ public Subject login(String username, char[] password, Subject subject)
+ throws LoginException {
+ CallbackHandler cbh = new AuthenticationCallbackHandler(username, password);
+ return loginEx(cbh, subject);
+ }
+
+ @Override
+ public Subject login(CallbackHandler cbh, Subject subject)
+ throws LoginException {
+ if (cbh == null)
+ throw new LoginException("AuthenticationService: JAAS CallbackHandler not supplied");
+
+ // TODO - Wrap CallbackHandler to obtain name for auditing
+ return loginEx(cbh, subject);
+ }
+
+ private Subject loginEx(CallbackHandler handler, Subject subject)
+ throws LoginException {
+ // Use the supplied Subject or create a new Subject
+ Subject _subject = subject;
+ if (_subject == null)
+ _subject = new Subject();
+
+ ClassLoader tcl = null;
+ boolean restoreTcl = false;
+ try {
+ // Unable to login without a JAAS Configuration instance
+ // TODO - Dynamic configuration handling?
+ if (configuration == null) {
+ throw new UnsupportedOperationException(
+ "JAAS Configuration setup incomplete, unable to perform login");
+ }
+
+ // Setup the PasswordCredential for the Realm LoginModules when configured
+ if (usePasswordCredential) {
+ setupPasswordCredential(_subject, handler);
+ }
+
+ // When needed, setup the Context ClassLoader so JAAS can load the LoginModule(s)
+ tcl = (ClassLoader) AppservAccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ final ClassLoader ccl = serverContext.getCommonClassLoader();
+ if (!ccl.equals(tcl)) {
+ AppservAccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ Thread.currentThread().setContextClassLoader(ccl);
+ return null;
+ }
+ });
+ restoreTcl = true;
+ }
+
+ // Perform the login via the JAAS LoginContext
+ LoginContext context = new LoginContext(name, _subject, handler, configuration);
+ context.login();
+ } catch (Exception exc) {
+ // TODO - Address Audit/Log/Debug handling options
+ if (exc instanceof LoginException)
+ throw (LoginException) exc;
+
+ throw (LoginException) new LoginException(
+ "AuthenticationService: "+ exc.getMessage()).initCause(exc);
+ } finally {
+ if (restoreTcl) {
+ final ClassLoader cl = tcl;
+ AppservAccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ Thread.currentThread().setContextClassLoader(cl);
+ return null;
+ }
+ });
+ }
+ }
+
+ // Return the Subject that was logged in
+ return _subject;
+ }
+
+ @Override
+ public Subject impersonate(String user, String[] groups, Subject subject, boolean virtual)
+ throws LoginException {
+ return impersonationService.impersonate(user, groups, subject, virtual);
+ }
+
+ /**
+ * Handle lookup of authentication service configuration and initialization.
+ * If no service is configured the service run-time will throw exceptions.
+ *
+ * Addresses alternate configuration handling until adopt @Proxiable support.
+ */
+ @Override
+ public void postConstruct() {
+ /*
+ * Realm-related classes uses Globals (they are not services)
+ * so make sure it is set up.
+ */
+ if (Globals.getDefaultBaseServiceLocator() == null) {
+ Globals.setDefaultHabitat(locator);
+ }
+ // TODO - Dynamic configuration changes?
+ initialize(AuthenticationServiceFactory.getAuthenticationServiceConfiguration(domain));
+ }
+
+ /**
+ * A PasswordCredential object is needed when using the existing Realm LoginModules.
+ *
+ * Unless the CallbackHandler is from the AuthenticationService obtain the name
+ * and password from the supplied JAAS CallbackHandler directly. Establishing the
+ * PasswordCredential in the Subject is determined by service configuration.
+ *
+ * @throws LoginException when unable to obtain data from the CallbackHandler
+ */
+ private void setupPasswordCredential(Subject subject, CallbackHandler callbackHandler)
+ throws LoginException {
+ String username = null;
+ char[] password = null;
+
+ // Obtain the username and password for the PasswordCredential
+ if (callbackHandler instanceof AuthenticationCallbackHandler) {
+ username = ((AuthenticationCallbackHandler) callbackHandler).getUsername();
+ password = ((AuthenticationCallbackHandler) callbackHandler).getPassword();
+ }
+ else {
+ // Use the supplied callback handler to obtain the PasswordCredential information
+ // TODO - How does this impact Audit ability to get name?
+ Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback("username: ");
+ callbacks[1] = new PasswordCallback("password: ", false);
+ try {
+ callbackHandler.handle(callbacks);
+ username = ((NameCallback) callbacks[0]).getName();
+ password = ((PasswordCallback) callbacks[1]).getPassword();
+ } catch (IOException ioe) {
+ throw (LoginException) new LoginException("AuthenticationService unable to create PasswordCredential: "+ ioe.getMessage()).initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw (LoginException) new LoginException("AuthenticationService unable to create PasswordCredential: "+ uce.getMessage()).initCause(uce);
+ }
+ }
+
+ // Add the PasswordCredential to the Subject
+ final Subject s = subject;
+ final PasswordCredential pc = new PasswordCredential(username, password, realmName);
+ AppservAccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ s.getPrivateCredentials().add(pc);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Convert the String setting to the JAAS LoginModuleControlFlag.
+ * An unknown or null flag value is treated as LoginModuleControlFlag.REQUIRED.
+ */
+ private LoginModuleControlFlag getLoginModuleControlFlag(String controlFlag) {
+ LoginModuleControlFlag flag = LoginModuleControlFlag.REQUIRED;
+ // TODO - Handle invalid control flag?
+ if (controlFlag != null) {
+ if ("required".equalsIgnoreCase(controlFlag))
+ return flag;
+ // Check additional flag types
+ if ("sufficient".equalsIgnoreCase(controlFlag))
+ flag = LoginModuleControlFlag.SUFFICIENT;
+ else if ("optional".equalsIgnoreCase(controlFlag))
+ flag = LoginModuleControlFlag.OPTIONAL;
+ else if ("requisite".equalsIgnoreCase(controlFlag))
+ flag = LoginModuleControlFlag.REQUISITE;
+ }
+ return flag;
+ }
+
+ /**
+ * The Authentication Service CallbackHandler implementation.
+ *
+ * Facilitates use of the standard JAAS NameCallback and PasswordCallback.
+ */
+ private static class AuthenticationCallbackHandler implements CallbackHandler {
+ private String user;
+ private char[] pass;
+
+ public AuthenticationCallbackHandler(String username, char[] password) {
+ user = username;
+ pass = password;
+ }
+
+ protected String getUsername() { return user; }
+ protected char[] getPassword() { return pass; }
+
+ @Override
+ public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback)
+ ((NameCallback) callbacks[i]).setName(user);
+ else if (callbacks[i] instanceof PasswordCallback)
+ ((PasswordCallback) callbacks[i]).setPassword(pass);
+ else
+ // TODO - Have configuration setting for throwing exception
+ throw new UnsupportedCallbackException(callbacks[i],
+ "AuthenticationCallbackHandler: Unrecognized Callback "
+ + callbacks[i].getClass().getName());
+ }
+ }
+ }
+
+ /**
+ * The Authentication Service JAAS Configuration implementation.
+ *
+ * Facilitates the use of JAAS LoginContext with Authentication Service LoginModule configuration.
+ */
+ private static class AuthenticationJaasConfiguration extends Configuration {
+ private String configurationName;
+ private AppConfigurationEntry[] lmEntries;
+
+ /**
+ * Create the JAAS Configuration instance used by the Authentication Service.
+ */
+ private AuthenticationJaasConfiguration(String name, ArrayList<AppConfigurationEntry> entries) {
+ configurationName = name;
+ lmEntries = entries.toArray(new AppConfigurationEntry[entries.size()]);
+ }
+
+ /**
+ * Get the LoginModule(s) specified by the Authentication Service configuration.
+ */
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
+ if (configurationName.equals(name))
+ return lmEntries;
+ else
+ return null;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ImpersonationServiceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ImpersonationServiceImpl.java
new file mode 100644
index 0000000..ca61211
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ImpersonationServiceImpl.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import java.security.Principal;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.inject.Singleton;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+
+import org.glassfish.security.common.Group;
+import org.glassfish.security.common.PrincipalImpl;
+import org.glassfish.security.services.api.authentication.ImpersonationService;
+import org.glassfish.security.services.common.Secure;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * The Impersonation Service Implementation.
+ *
+ * @author jazheng
+ */
+@Service(name="impersonationService")
+@Singleton
+@Secure(accessPermissionName = "security/service/impersonation/simple")
+public class ImpersonationServiceImpl implements ImpersonationService {
+
+ static final Logger LOG = Logger
+ .getLogger(ImpersonationServiceImpl.class.getName());
+
+ @Override
+ public Subject impersonate(String user, String[] groups, Subject subject,
+ boolean virtual) throws LoginException {
+
+ // Use the supplied Subject or create a new Subject
+ final Subject _subject =
+ (subject != null)? subject: new Subject();
+
+ if (user == null || user.isEmpty()) {
+ return _subject;
+ }
+
+ // TODO - Add support for virtual = false after IdentityManager
+ // is available in open source
+ if (!virtual) {
+ throw new UnsupportedOperationException(
+ "Use of non-virtual parameter is not supported");
+ } else {
+ // Build the Subject
+ Set<Principal> principals = _subject.getPrincipals();
+ principals.add(new PrincipalImpl(user));
+ if (groups != null) {
+ for (String group: groups) {
+ principals.add(new Group(group));
+ }
+ }
+ }
+
+ // Return the impersonated Subject
+ return _subject;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSDomainPasswordAliasStore.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSDomainPasswordAliasStore.java
new file mode 100644
index 0000000..03310cc
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSDomainPasswordAliasStore.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import com.sun.enterprise.security.store.DomainScopedPasswordAliasStore;
+import com.sun.enterprise.security.store.IdentityManagement;
+import com.sun.enterprise.util.SystemPropertyConstants;
+import java.io.File;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.security.services.common.Secure;
+import org.jvnet.hk2.annotations.Optional;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * Exposes as a service the JCEKS implementation of the
+ * domain-scoped password alias store.
+ * @author tjquinn
+ */
+@Service
+@Named("JCEKS")
+@PerLookup
+@Secure(accessPermissionName = "security/service/credential/provider/jceks")
+public class JCEKSDomainPasswordAliasStore extends JCEKSPasswordAliasStore implements DomainScopedPasswordAliasStore {
+
+ private static final String PASSWORD_ALIAS_KEYSTORE = "domain-passwords";
+
+ @Inject @Optional
+ private IdentityManagement idm;
+
+ @PostConstruct
+ private void initStore() {
+ try {
+ init(pathToDomainAliasStore(), getMasterPassword());
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private char[] getMasterPassword() {
+ return idm == null ? null : idm.getMasterPassword();
+ }
+
+ private static String pathToDomainAliasStore() {
+ return System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY) +
+ File.separator + "config" + File.separator + PASSWORD_ALIAS_KEYSTORE;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSPasswordAliasStore.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSPasswordAliasStore.java
new file mode 100644
index 0000000..971427b
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/JCEKSPasswordAliasStore.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import com.sun.enterprise.security.store.PasswordAdapter;
+import com.sun.enterprise.util.Utility;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.crypto.SecretKey;
+import org.glassfish.api.admin.PasswordAliasStore;
+
+/**
+ * Provides the PasswordAliasStore behavior using a JCEKS keystore.
+ * <p>
+ * The keystore is actually managed by the PasswordAdapter, to which
+ * this implementation currently delegates its work.
+ * <p>
+ * Note that this service is currently per-lookup. This is so that each
+ * use of the alias store gets the current on-disk information. Ideally we can change this
+ * when we can use Java 7 features, including the WatchService feature.
+ * <p>
+ * This class's methods are not
+ * synchronized because the PasswordAdapter's methods are. If this implementation
+ * changes so that it no longer delegates to those synchronized PasswordAdapter
+ * methods, then make sure that the implementation is thread-safe.
+ * <p>
+ * Note that the domain-scoped password alias store service class extends this
+ * class. As a service, that class will be instantiated using the no-args
+ * constructor. So the actual initialization of the class occurs in the init
+ * method. The domain-scoped service class invokes the init method itself.
+ * Any code that needs to create some other alias store can use the newInstance
+ * method to provide the location of the alias store file and the password.
+ *
+ * @author tjquinn
+ */
+public class JCEKSPasswordAliasStore implements PasswordAliasStore {
+
+ private final static Charset utf8 = Charset.forName("UTF-8");
+
+ private PasswordAdapter pa = null;
+ private String pathToAliasStore;
+ private char[] storePassword;
+
+ protected final void init(final String pathToAliasStore, final char[] storePassword) {
+ this.pathToAliasStore = pathToAliasStore;
+ this.storePassword = storePassword;
+ }
+
+ private synchronized PasswordAdapter pa() {
+ if (pa == null) {
+ try {
+ pa = new PasswordAdapter(pathToAliasStore, storePassword);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return pa;
+ }
+
+ public static JCEKSPasswordAliasStore newInstance(final String pathToAliasStore, final char[] storePassword) {
+ final JCEKSPasswordAliasStore result = new JCEKSPasswordAliasStore();
+ result.init(pathToAliasStore, storePassword);
+ return result;
+ }
+
+ @Override
+ public void clear() {
+ try {
+ for (Enumeration<String> aliasEnum = pa().getAliases(); aliasEnum.hasMoreElements(); ) {
+ pa().removeAlias(aliasEnum.nextElement());
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void put(String alias, char[] password) {
+ final CharBuffer charBuffer = CharBuffer.wrap(password);
+ final ByteBuffer byteBuffer = utf8.encode(charBuffer);
+ try {
+ pa().setPasswordForAlias(alias, Utility.toByteArray(byteBuffer));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void putAll(PasswordAliasStore otherStore) {
+ final Map<String,char[]> entries = new HashMap<String,char[]>();
+ for (Iterator<String> aliasIt = otherStore.keys(); aliasIt.hasNext();) {
+ final String alias = aliasIt.next();
+ entries.put(alias, otherStore.get(alias));
+ }
+ putAll(entries);
+ }
+
+ @Override
+ public void putAll(Map<String, char[]> settings) {
+ for (Map.Entry<String,char[]> entry : settings.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ settings.clear();
+ }
+
+ @Override
+ public void remove(String alias) {
+ try {
+ pa().removeAlias(alias);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public boolean containsKey(String alias) {
+ try {
+ return pa().aliasExists(alias);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public char[] get(String alias) {
+ try {
+ final SecretKey secretKey = pa().getPasswordSecretKeyForAlias(alias);
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(secretKey.getEncoded());
+ return Utility.toCharArray(utf8.decode(byteBuffer));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ @Override
+ public Iterator<String> keys() {
+ final List<String> keys = new ArrayList<String>();
+ try {
+ for (Enumeration<String> aliases = pa().getAliases(); aliases.hasMoreElements(); keys.add(aliases.nextElement())) {}
+ return keys.iterator();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public int size() {
+ try {
+ int size = 0;
+ for (Enumeration<String> aliases = pa().getAliases(); aliases.hasMoreElements(); size++, aliases.nextElement() ) {}
+ return size;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/NucleusInternalSystemAdministrator.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/NucleusInternalSystemAdministrator.java
new file mode 100644
index 0000000..0907598
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/NucleusInternalSystemAdministrator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import javax.inject.Singleton;
+import org.glassfish.security.services.api.authentication.AbstractInternalSystemAdministrator;
+import org.glassfish.security.services.api.authorization.AuthorizationAdminConstants;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * Nucleus (open-source) implementation of the InternalSystemAdministrator contract.
+ *
+ * @author tjquinn
+ */
+@Service(name="nucleus")
+@Singleton
+public class NucleusInternalSystemAdministrator extends AbstractInternalSystemAdministrator {
+
+ @Override
+ protected String getInternalUsername() {
+ return "_InternalSystemAdministrator_";
+ }
+
+ @Override
+ protected String getAdminGroupName() {
+ return AuthorizationAdminConstants.ADMIN_GROUP;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceFactory.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceFactory.java
new file mode 100644
index 0000000..8f772be
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import java.util.List;
+
+import org.glassfish.security.services.config.SecurityConfigurations;
+import org.glassfish.security.services.config.SecurityConfiguration;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+
+/**
+ * The base security service factory class.
+ */
+public class ServiceFactory {
+ /**
+ * Get the security service configuration for the specified service type.
+ *
+ * Attempt to obtain the service configuration marked as default
+ * otherwise use the first configured service instance.
+ *
+ * @param domain The current Domain configuration object
+ * @param type The type of the security service configuration
+ *
+ * @return null when no service configurations are found
+ */
+ public static <T extends SecurityConfiguration> T getSecurityServiceConfiguration(Domain domain, Class<T> type) {
+ T config = null;
+
+ // Look for security service configurations
+ SecurityConfigurations secConfigs = domain.getExtensionByType(SecurityConfigurations.class);
+ if (secConfigs != null) {
+ // Look for the service configuration marked default
+ config = secConfigs.getDefaultSecurityServiceByType(type);
+ if (config == null) {
+ // Obtain the first service configuration listed
+ List<T> configs = secConfigs.getSecurityServicesByType(type);
+ if (!configs.isEmpty())
+ config = configs.get(0);
+ }
+ }
+
+ // Return the service configuration
+ return config;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceLogging.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceLogging.java
new file mode 100644
index 0000000..63c83c3
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/ServiceLogging.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import org.glassfish.logging.annotation.LogMessagesResourceBundle;
+import org.glassfish.logging.annotation.LoggerInfo;
+
+/**
+ * The security service logging class.
+ */
+public class ServiceLogging {
+ @LogMessagesResourceBundle
+ public static final String SHARED_LOGMESSAGE_RESOURCE = "org.glassfish.security.services.LogMessages";
+
+ @LoggerInfo(subsystem="SECSVCS", description="Security Services Logger", publish=true)
+ public static final String SEC_SVCS_LOGGER = "javax.enterprise.security.services";
+
+ @LoggerInfo(subsystem="SECPROV", description="Security Provider Logger", publish=true)
+ public static final String SEC_PROV_LOGGER = "javax.enterprise.security.services.provider";
+
+ @LoggerInfo(subsystem="SECCMDS", description="Security Services Command Logger", publish=true)
+ public static final String SEC_COMMANDS_LOGGER = "javax.enterprise.security.services.commands";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImpl.java
new file mode 100644
index 0000000..38ee6ff
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImpl.java
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import java.net.URI;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.security.Policy;
+import java.security.CodeSource;
+import java.security.CodeSigner;
+import javax.security.auth.Subject;
+
+import org.glassfish.security.services.api.authorization.AuthorizationService;
+import org.glassfish.security.services.api.authorization.AzAction;
+import org.glassfish.security.services.api.authorization.AzResource;
+import org.glassfish.security.services.api.authorization.AzResult;
+import org.glassfish.security.services.api.authorization.AzSubject;
+import org.glassfish.security.services.api.context.SecurityContextService;
+import org.glassfish.security.services.common.PrivilegedLookup;
+import org.glassfish.security.services.common.Secure;
+import org.glassfish.security.services.config.SecurityConfiguration;
+import org.glassfish.security.services.impl.ServiceFactory;
+import org.glassfish.security.services.impl.ServiceLogging;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.ServiceLocator;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.logging.annotation.LogMessageInfo;
+
+import org.glassfish.security.services.api.authorization.*;
+import org.glassfish.security.services.api.common.Attributes;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.spi.authorization.AuthorizationProvider;
+
+/**
+ * <code>AuthorizationServiceImpl</code> implements
+ * <code>{@link org.glassfish.security.services.api.authorization.AuthorizationService}</code>
+ * by delegating authorization decisions to configured
+ * <code>{@link org.glassfish.security.services.spi.AuthorizationProvider}</code>
+ * instances.
+ */
+@Service
+@Singleton
+@Secure(accessPermissionName = "security/service/authorization")
+public final class AuthorizationServiceImpl implements AuthorizationService, PostConstruct {
+ private static final Level DEBUG_LEVEL = Level.FINER;
+ private static final Logger logger =
+ Logger.getLogger(ServiceLogging.SEC_SVCS_LOGGER,ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(AuthorizationServiceImpl.class);
+ @Inject
+ private volatile Domain domain;
+
+ @Inject
+ private volatile ServiceLocator serviceLocator;
+
+ private volatile org.glassfish.security.services.config.AuthorizationService atzSvCfg;
+
+ @Inject
+ private volatile SecurityContextService securityContextService;
+
+ private volatile SecurityProvider atzPrvConfig;
+
+ private volatile AuthorizationProvider provider;
+
+ private static final CodeSource NULL_CODESOURCE = new CodeSource(null, (CodeSigner[])null);
+
+ enum InitializationState {
+ NOT_INITIALIZED,
+ SUCCESS_INIT,
+ FAILED_INIT
+ }
+ private volatile InitializationState initialized = InitializationState.NOT_INITIALIZED;
+ private volatile String reasonInitFailed =
+ localStrings.getLocalString("service.atz.never_init","Authorization Service never initialized.");
+
+ private final List<AzAttributeResolver> attributeResolvers =
+ Collections.synchronizedList(new java.util.ArrayList<AzAttributeResolver>());
+
+ private boolean isDebug() {
+ return logger.isLoggable(DEBUG_LEVEL);
+ }
+
+ /**
+ * Initialize the security service instance with the specific security service configuration.
+ *
+ * @see org.glassfish.security.services.api.SecurityService#initialize
+ */
+ @Override
+ public void initialize(final SecurityConfiguration securityServiceConfiguration) {
+
+ if ( InitializationState.NOT_INITIALIZED != initialized ) {
+ return;
+ }
+
+ try {
+ // Get service level config
+ if ( !( securityServiceConfiguration instanceof org.glassfish.security.services.config.AuthorizationService ) ) {
+ throw new IllegalStateException(
+ localStrings.getLocalString("service.atz.not_config","The Authorization service is not configured in the domain configuration file."));
+ }
+ atzSvCfg = (org.glassfish.security.services.config.AuthorizationService) securityServiceConfiguration;
+
+ // Get provider level config, consider only one provider for now and take the first provider found.
+ List<SecurityProvider> providersConfig = atzSvCfg.getSecurityProviders();
+ if ( (providersConfig == null) || ( (atzPrvConfig = providersConfig.get(0)) == null ) ) {
+ throw new IllegalStateException(
+ localStrings.getLocalString("service.atz.no_prov_config","No provider configured for the Authorization service in the domain configuration file."));
+ }
+
+ // Get the provider
+ final String providerName = atzPrvConfig.getName();
+ if ( isDebug() ) {
+ logger.log(DEBUG_LEVEL, "Attempting to get Authorization provider \"{0}\".", providerName );
+ }
+ provider = AccessController.doPrivileged(
+ new PrivilegedLookup<AuthorizationProvider>(
+ serviceLocator, AuthorizationProvider.class, providerName));
+ if (provider == null) {
+ throw new IllegalStateException(
+ localStrings.getLocalString("service.atz.not_provider","Authorization Provider {0} not found.", providerName));
+ }
+
+ // Initialize the provider
+ provider.initialize(atzPrvConfig);
+
+ initialized = InitializationState.SUCCESS_INIT;
+ reasonInitFailed = null;
+
+ logger.log(Level.INFO, ATZSVC_INITIALIZED);
+
+ } catch ( Exception e ) {
+ String eMsg = e.getMessage();
+ String eClass = e.getClass().getName();
+ reasonInitFailed = localStrings.getLocalString("service.atz.init_failed",
+ "Authorization Service initialization failed, exception {0}, message {1}", eClass, eMsg);
+ logger.log(Level.WARNING, ATZSVC_INIT_FAILED, new Object[] {eClass, eMsg});
+ throw new RuntimeException( reasonInitFailed, e );
+ } finally {
+ if ( InitializationState.SUCCESS_INIT != initialized ) {
+ initialized = InitializationState.FAILED_INIT;
+ }
+ }
+ }
+
+ /**
+ * Determine whether the given Subject has been granted the specified Permission
+ * by delegating to the configured java.security.Policy object. This method is
+ * a high-level convenience method that tests for a Subject-based permission
+ * grant without reference to the AccessControlContext of the caller.
+ *
+ * In addition, this method isolates the query from the underlying Policy configuration
+ * model. It could, for example, multiplex queries across multiple instances of Policy
+ * configured in an implementation-specific way such that different threads, or different
+ * applications, query different Policy objects. The initial implementation simply
+ * delegates to the configured Policy as defined by Java SE.
+ *
+ * @param subject The Subject for which permission is being tested.
+ * @param permission The Permission being queried.
+ * @return True or false, depending on whether the specified Permission
+ * is granted to the Subject by the configured Policy.
+ * @throws IllegalArgumentException Given null or illegal subject or permission
+ * @see AuthorizationService#isPermissionGranted(javax.security.auth.Subject, java.security.Permission)
+ */
+ @Override
+ public boolean isPermissionGranted(
+ final Subject subject, final Permission permission) {
+
+ // Validate inputs
+ if ( null == subject ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.subject_null", "The supplied Subject is null."));
+ }
+ if ( null == permission ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.permission_null","The supplied Permission is null."));
+ }
+
+ Set<Principal> principalset = subject.getPrincipals();
+ Principal[] principalAr = (principalset.size() == 0) ? null : principalset.toArray(new Principal[principalset.size()]);
+ ProtectionDomain pd = new ProtectionDomain(NULL_CODESOURCE, null, null, principalAr);
+ Policy policy = Policy.getPolicy();
+ boolean result = policy.implies(pd, permission);
+
+ return result;
+ }
+
+
+ /**
+ * Determine whether the given Subject is authorized to access the given resource,
+ * specified by a URI.
+ *
+ * @param subject The Subject being tested.
+ * @param resource URI of the resource being tested.
+ * @return True or false, depending on whether the access is authorized.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ * @see AuthorizationService#isAuthorized(javax.security.auth.Subject, java.net.URI)
+ */
+ @Override
+ public boolean isAuthorized(Subject subject, URI resource) {
+ return isAuthorized(subject, resource, null);
+ }
+
+
+ /**
+ * Determine whether the given Subject is authorized to access the given resource,
+ * specified by a URI.
+ *
+ * @param subject The Subject being tested.
+ * @param resource URI of the resource being tested.
+ * @param action The action, with respect to the resource parameter,
+ * for which authorization is desired. To check authorization for all actions,
+ * action is represented by null or "*".
+ * @return True or false, depending on whether the access is authorized.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ * @see AuthorizationService#isAuthorized(javax.security.auth.Subject, java.net.URI, String)
+ */
+ @Override
+ public boolean isAuthorized(final Subject subject, final URI resource, final String action) {
+
+ checkServiceAvailability();
+
+ // Validate inputs
+ if ( null == subject ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.subject_null", "The supplied Subject is null."));
+ }
+ if ( null == resource ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.resource_null", "The supplied Resource is null."));
+ }
+ // Note: null action means all actions (i.e., no action condition)
+
+ // Convert parameters
+ AzSubject azSubject = makeAzSubject( subject );
+ AzResource azResource = makeAzResource( resource );
+ AzAction azAction = makeAzAction(action);
+
+ AzResult azResult = getAuthorizationDecision(azSubject, azResource, azAction);
+
+ boolean result =
+ AzResult.Status.OK.equals(azResult.getStatus()) &&
+ AzResult.Decision.PERMIT.equals(azResult.getDecision());
+ return result;
+ }
+
+
+ /**
+ * The primary authorization method. The isAuthorized() methods call this method
+ * after converting their arguments into the appropriate attribute collection type.
+ * It returns a full AzResult, including authorization status, decision, and
+ * obligations.
+ *
+ * This method performs two steps prior to invoking the configured AuthorizationProvider
+ * to evaluate the request: First, it acquires the current AzEnvironment attributes by
+ * calling the Security Context service. Second, it calls the Role Mapping service to
+ * determine which roles the subject has, and adds the resulting role attributes into
+ * the AzSubject.
+ *
+ * @param subject The attributes collection representing the Subject for which an authorization
+ * decision is requested.
+ * @param resource The attributes collection representing the resource for which access is
+ * being requested.
+ * @param action The attributes collection representing the action, with respect to the resource,
+ * for which access is being requested. A null action is interpreted as all
+ * actions, however all actions may also be represented by the AzAction instance.
+ * See <code>{@link org.glassfish.security.services.api.authorization.AzAction}</code>.
+ * @return The AzResult indicating the result of the access decision.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Service was not initialized.
+ * @see AuthorizationService#getAuthorizationDecision
+ */
+ @Override
+ public AzResult getAuthorizationDecision(
+ final AzSubject subject,
+ final AzResource resource,
+ final AzAction action) {
+
+ checkServiceAvailability();
+
+ // Validate inputs
+ if ( null == subject ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.subject_null", "The supplied Subject is null."));
+ }
+ if ( null == resource ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.resource_null", "The supplied Resource is null."));
+ }
+
+ // TODO: setup current AzEnvironment instance. Should a null or empty instance to represent current environment?
+ final AzEnvironment env = new AzEnvironmentImpl();
+ final Attributes attrs = securityContextService.getEnvironmentAttributes();
+ for (String attrName : attrs.getAttributeNames()) {
+ env.addAttribute(attrName, attrs.getAttributeValue(attrName), true);
+ }
+
+ AzResult result = provider.getAuthorizationDecision(
+ subject, resource, action, env, attributeResolvers );
+
+ if ( isDebug() ) {
+ logger.log(DEBUG_LEVEL,
+ "Authorization Service result for {0} was {1}.",
+ new String[]{ subject.toString(), result.toString() } );
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Convert a Java Subject into a typed attributes collection.
+ *
+ * @param subject The Subject to convert.
+ * @return The resulting AzSubject.
+ * @throws IllegalArgumentException Given null or illegal subject
+ * @see AuthorizationService#makeAzSubject(javax.security.auth.Subject)
+ */
+ @Override
+ public AzSubject makeAzSubject(final Subject subject) {
+ AzSubject azs = new AzSubjectImpl(subject);
+ return azs;
+ }
+
+
+ /**
+ * Convert a resource, expressed as a URI, into a typed attributes collection.
+ * <p>
+ * Query parameters in the given URI are appended to this
+ * <code>AzResource</code> instance attributes collection.
+ *
+ * @param resource The URI to convert.
+ * @return The resulting AzResource.
+ * @see AuthorizationService#makeAzResource(java.net.URI)
+ * @throws IllegalArgumentException Given null or illegal resource
+ */
+ @Override
+ public AzResource makeAzResource(final URI resource) {
+ AzResource azr = new AzResourceImpl( resource );
+ return azr;
+ }
+
+
+ /**
+ * Convert an action, expressed as a String, into a typed attributes collection.
+ *
+ * @param action The action to convert. null or "*" represents all actions.
+ * @return The resulting AzAction.
+ * @see AuthorizationService#makeAzAction(String)
+ */
+ @Override
+ public AzAction makeAzAction(final String action) {
+ AzAction aza = new AzActionImpl( action );
+ return aza;
+ }
+
+
+ /**
+ * Find an existing PolicyDeploymentContext, or create a new one if one does not
+ * already exist for the specified appContext. The context will be returned in
+ * an "open" state, and will stay that way until commit() or delete() is called.
+ *
+ * @param appContext The application context for which the PolicyDeploymentContext
+ * is desired.
+ * @return The resulting PolicyDeploymentContext,
+ * null if the configured providers do not support this feature.
+ * @throws IllegalStateException Service was not initialized.
+ * @see AuthorizationService#findOrCreateDeploymentContext(String)
+ */
+ @Override
+ public PolicyDeploymentContext findOrCreateDeploymentContext(
+ final String appContext) {
+
+ checkServiceAvailability();
+
+ // TODO: Unsupported Operation Exception undocumented, not optional
+
+ return provider.findOrCreateDeploymentContext(appContext);
+ }
+
+
+ /**
+ * Called when the instance has been created and the component is
+ * about to be place into commission.
+ * <p>
+ * The component has been injected with any dependency and
+ * will be placed into commission by the subsystem.
+ * <p>
+ * Hk2 will catch all unchecked exceptions,
+ * and will consequently cause the backing inhabitant to be released.
+ *
+ * @see org.glassfish.hk2.api.PostConstruct#postConstruct()
+ */
+ @Override
+ public void postConstruct() {
+
+ org.glassfish.security.services.config.AuthorizationService atzConfiguration =
+ ServiceFactory.getSecurityServiceConfiguration(
+ domain, org.glassfish.security.services.config.AuthorizationService.class);
+
+ initialize(atzConfiguration);
+ }
+
+
+ /**
+ * Appends the given <code>{@link org.glassfish.security.services.api.authorization.AzAttributeResolver}</code>
+ * instance to the internal ordered list of <code>AzAttributeResolver</code> instances,
+ * if not currently in the list based on
+ * <code>{@link org.glassfish.security.services.api.authorization.AzAttributeResolver#equals}</code>.
+ *
+ * @param resolver The <code>AzAttributeResolver</code> instance to append.
+ * @return true if the <code>AzAttributeResolver</code> was added,
+ * false if the <code>AzAttributeResolver</code> was already in the list.
+ * @throws IllegalArgumentException Given AzAttributeResolver was null.
+ * @see AuthorizationService#appendAttributeResolver
+ */
+ @Override
+ public boolean appendAttributeResolver(AzAttributeResolver resolver) {
+ if ( null == resolver ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.resolver_null","The supplied Attribute Resolver is null."));
+ }
+ synchronized ( attributeResolvers ) {
+ if ( !attributeResolvers.contains( resolver ) ) {
+ attributeResolvers.add( resolver );
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Replaces the internal list of <code>AttributeResolver</code> instances
+ * with the given list. If multiple equivalent instances exist in the given list,
+ * only the first such instance will be inserted.
+ *
+ * @param resolverList Replacement list of <code>AzAttributeResolver</code> instances
+ * @throws IllegalArgumentException Given AzAttributeResolver list was null.
+ * @see AuthorizationService#setAttributeResolvers
+ */
+ @Override
+ public void setAttributeResolvers(List<AzAttributeResolver> resolverList) {
+ if ( null == resolverList ) {
+ throw new IllegalArgumentException(localStrings.getLocalString("service.resolver_null","The supplied Attribute Resolver is null."));
+ }
+
+ synchronized ( attributeResolvers ) {
+ attributeResolvers.clear();
+ for ( AzAttributeResolver ar : resolverList ) {
+ if ( (null != ar) && !attributeResolvers.contains(ar) ) {
+ attributeResolvers.add( ar );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Determines the current list of <code>AttributeResolver</code> instances,
+ * in execution order.
+ *
+ * @return The current list of AttributeResolver instances,
+ * in execution order.
+ * @see AuthorizationService#getAttributeResolvers
+ */
+ @Override
+ public List<AzAttributeResolver> getAttributeResolvers() {
+ return new ArrayList<AzAttributeResolver>( attributeResolvers );
+ }
+
+
+ /**
+ * Removes all <code>AttributeResolver</code> instances from the current
+ * internal list of <code>AttributeResolver</code> instances.
+ *
+ * @return true if any <code>AttributeResolver</code> instances were removed,
+ * false if the list was empty.
+ * @see AuthorizationService#removeAllAttributeResolvers
+ */
+ @Override
+ public boolean removeAllAttributeResolvers() {
+ synchronized ( attributeResolvers ) {
+ if ( attributeResolvers.isEmpty() ) {
+ return false;
+ } else {
+ attributeResolvers.clear();
+ return true;
+ }
+ }
+ }
+
+
+ /**
+ * Determines whether this service has been initialized.
+ * @return The initialization state
+ */
+ final InitializationState getInitializationState() {
+ return initialized;
+ }
+
+
+ /**
+ * Determines the reason why the service failed to initialize.
+ * @return The reason why the service failed to initialize,
+ * null if initialization was successful or the failure reason was unknown.
+ */
+ final String getReasonInitializationFailed() {
+ return reasonInitFailed;
+ }
+
+
+ /**
+ * Checks whether this service is available.
+ * @throws IllegalStateException This service is not available.
+ */
+ final void checkServiceAvailability() {
+ if ( InitializationState.SUCCESS_INIT != getInitializationState() ) {
+ throw new IllegalStateException(
+ localStrings.getLocalString("service.atz.not_avail","The Authorization service is not available.") +
+ getReasonInitializationFailed() );
+ }
+ }
+
+ //
+ // Log Messages
+ //
+
+ @LogMessageInfo(
+ message = "Authorization Service has successfully initialized.",
+ level = "INFO")
+ private static final String ATZSVC_INITIALIZED = "SEC-SVCS-00100";
+
+ @LogMessageInfo(
+ message = "Authorization Service initialization failed, exception {0}, message {1}",
+ level = "WARNING")
+ private static final String ATZSVC_INIT_FAILED = "SEC-SVCS-00101";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzActionImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzActionImpl.java
new file mode 100755
index 0000000..f206937
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzActionImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzAction;
+
+public final class AzActionImpl extends AzAttributesImpl implements AzAction {
+
+ private final String action;
+
+
+ /**
+ * Constructor
+ *
+ * @param action The represented action, null or "*" to represent all actions
+ */
+ public AzActionImpl( String action ) {
+ super( NAME );
+
+ if ( "*".equals( action ) ) {
+ action = null;
+ }
+ this.action = action;
+ }
+
+
+ /**
+ * Determines the action represented as a string.
+ * @return The represented action, null represents all actions
+ * @see org.glassfish.security.services.api.authorization.AzAction#getAction()
+ */
+ @Override
+ public String getAction() {
+ return action;
+ }
+
+
+ /**
+ * Determines the represented action, "*" represents all actions
+ * @return The represented action.
+ */
+ @Override
+ public String toString() {
+ return action == null ? "*" : action;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzAttributesImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzAttributesImpl.java
new file mode 100755
index 0000000..9734ab5
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzAttributesImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzAttributes;
+import org.glassfish.security.services.impl.common.AttributesImpl;
+
+/**
+ * <code>AzAttributesImpl</code> implements AzAttributes to provide an abstract
+ * layer specifically for Authorization attributes.
+ */
+public abstract class AzAttributesImpl extends AttributesImpl implements AzAttributes {
+
+ private final String name;
+
+
+ /**
+ * Copy constructor
+ *
+ * @param other The copy source
+ */
+ public AzAttributesImpl( AzAttributesImpl other ) {
+ super( other );
+
+ this.name = other.getName();
+ }
+
+
+ /**
+ * Constructor
+ * @param name The name of this collection.
+ * @throws IllegalArgumentException Given name is null or empty
+ */
+ public AzAttributesImpl( String name ) {
+
+ if ( null == name ) {
+ throw new IllegalArgumentException( "Illegal null name given." );
+ }
+
+ name = name.trim();
+ if ( name.isEmpty() ) {
+ throw new IllegalArgumentException( "Illegal empty name given." );
+ }
+
+ this.name = name;
+ }
+
+ /**
+ * Determines a name to denote this collection of attributes.
+ * <p>
+ * For example, this name may be used to qualify attributes by collection
+ * type in XACML.
+ *
+ * @return The collection name
+ * @see org.glassfish.security.services.api.authorization.AzAttributes#getName()
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzEnvironmentImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzEnvironmentImpl.java
new file mode 100755
index 0000000..96c3cfb
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzEnvironmentImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzEnvironment;
+
+public final class AzEnvironmentImpl extends AzAttributesImpl implements AzEnvironment {
+
+ /**
+ * Constructor
+ */
+ public AzEnvironmentImpl() {
+ super( NAME );
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzObligationsImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzObligationsImpl.java
new file mode 100755
index 0000000..3937547
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzObligationsImpl.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzObligations;
+
+public final class AzObligationsImpl extends AzAttributesImpl implements AzObligations {
+
+ /**
+ * Constructor
+ */
+ public AzObligationsImpl() {
+ super(NAME);
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResourceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResourceImpl.java
new file mode 100755
index 0000000..aa729ef
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResourceImpl.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.logging.annotation.LogMessageInfo;
+import org.glassfish.security.services.api.authorization.AzResource;
+import org.glassfish.security.services.api.common.Attributes;
+import org.glassfish.security.services.impl.ServiceLogging;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public final class AzResourceImpl extends AzAttributesImpl implements AzResource {
+
+
+ private static final Logger logger = Logger.getLogger(ServiceLogging.SEC_SVCS_LOGGER,ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+
+ private static final boolean REPLACE = true;
+
+
+ private final URI uri;
+
+
+ /**
+ * Constructor
+ *
+ * @param resource The represented resource
+ * @throws IllegalArgumentException Given resource was null
+ */
+ public AzResourceImpl( URI resource ) {
+ super(NAME);
+
+ if ( null == resource ) {
+ throw new IllegalArgumentException("Illegal null resource URI.");
+ }
+ this.uri = resource;
+
+ // Dump the query parameters into the attribute map.
+ addAttributesFromUriQuery( uri, this, !REPLACE );
+ }
+
+
+ /**
+ * Determines the URI representing this resource.
+ * @return The URI representing this resource., never null.
+ */
+ @Override
+ public URI getUri() {
+ return uri;
+ }
+
+
+ /**
+ * Determines the URI used to initialize this resource.
+ * @return The URI used to initialize this resource.
+ */
+ @Override
+ public String toString() {
+ return uri.toString();
+ }
+
+
+ /**
+ * Yet another URI query parser, but this one knows how to populate
+ * <code>{@link org.glassfish.security.services.api.common.Attributes}</code>.
+ *
+ * @param uri The URI from which the query will be derived.
+ * @param attributes Attributes collection to populate
+ * @param replace true to replace entire attribute, false to append value to attribute.
+ * See <code>{@link org.glassfish.security.services.api.common.Attributes#addAttribute}</code>.
+ * @throws IllegalArgumentException URI or Attributes is null.
+ */
+ static void addAttributesFromUriQuery( URI uri, Attributes attributes, boolean replace ) {
+ if ( null == uri ) {
+ throw new IllegalArgumentException( "Illegal null URI." );
+ }
+ if ( null == attributes ) {
+ throw new IllegalArgumentException( "Illegal null Attributes." );
+ }
+
+ String query = uri.getRawQuery();
+ if ( ( null != query ) && ( query.length() > 0 ) ) {
+ String[] params = query.split( "&" );
+ if ( ( null != params ) && ( params.length > 0 ) ) {
+ for ( String nv : params ) {
+ if ( (null == nv) || (nv.length() <= 0) ) {
+ continue;
+ }
+
+ String name, value;
+ int equalsPos = nv.indexOf( "=" );
+ if ( -1 == equalsPos ) {
+ name = decodeURI( nv );
+ value = "";
+ } else {
+ name = decodeURI( nv.substring( 0, equalsPos ) );
+ value = decodeURI( nv.substring( equalsPos + 1 ) );
+ }
+
+ attributes.addAttribute( name, value, replace );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * URI decode the input, assumes UTF-8 encoding.
+ *
+ * @param input The input to decode.
+ * @return The decoded input, null returns null.
+ */
+ static String decodeURI( String input ) {
+ if ( null == input ) {
+ return null;
+ }
+
+ String output = input;
+ try {
+ output = URLDecoder.decode(input, "UTF-8");
+ } catch ( UnsupportedEncodingException e ) {
+ if ( logger.isLoggable( Level.WARNING ) ) {
+ logger.log( Level.WARNING, URI_DECODING_ERROR, e.getLocalizedMessage() );
+ }
+ }
+
+ return output;
+ }
+
+ @LogMessageInfo(
+ message = "Unable to decode URI: {0}.",
+ level = "WARNING")
+ private static final String URI_DECODING_ERROR = "SEC-SVCS-00102";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResultImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResultImpl.java
new file mode 100755
index 0000000..cf907a7
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzResultImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzObligations;
+import org.glassfish.security.services.api.authorization.AzResult;
+
+import java.text.MessageFormat;
+
+public final class AzResultImpl implements AzResult {
+
+ private final Decision decision;
+ private final Status status;
+ private final AzObligations obligations;
+
+ public AzResultImpl(Decision d, Status s, AzObligations o) {
+ decision = d;
+ status = s;
+ obligations = o;
+ }
+
+ public Decision getDecision() {
+ return decision;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public AzObligations getObligations() {
+ return obligations;
+ }
+
+
+ @Override
+ public String toString() {
+ return MessageFormat.format("status={0}, decision=[1]",
+ status, decision);
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzSubjectImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzSubjectImpl.java
new file mode 100755
index 0000000..0980d4f
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/AzSubjectImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.AzSubject;
+
+import javax.security.auth.Subject;
+
+public final class AzSubjectImpl extends AzAttributesImpl implements AzSubject {
+
+ final private Subject subject;
+
+ /**
+ * Constructor
+ *
+ * @param subject The represented subject
+ * @throws IllegalArgumentException Given subject was null
+ */
+ public AzSubjectImpl( Subject subject ) {
+ super(NAME);
+
+ if ( null == subject ) {
+ throw new IllegalArgumentException("Illegal null Subject.");
+ }
+ this.subject = subject;
+ }
+
+
+ /**
+ * Determines the <code>{@link javax.security.auth.Subject}</code>
+ * represented by this AzSubject.
+ * @return The represented Subject.
+ */
+ @Override
+ public final Subject getSubject() {
+ return subject;
+ }
+
+
+ @Override
+ public String toString() {
+ return subject.toString();
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImpl.java
new file mode 100644
index 0000000..dda6d48
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImpl.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import java.net.URI;
+import java.security.AccessController;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.security.auth.Subject;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.hk2.api.ServiceLocator;
+
+import org.glassfish.security.services.api.authorization.AzAttributeResolver;
+import org.glassfish.security.services.api.authorization.AzResource;
+import org.glassfish.security.services.api.authorization.AzSubject;
+import org.glassfish.security.services.api.authorization.RoleMappingService;
+import org.glassfish.security.services.common.PrivilegedLookup;
+import org.glassfish.security.services.common.Secure;
+import org.glassfish.security.services.config.SecurityConfiguration;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.impl.ServiceFactory;
+import org.glassfish.security.services.impl.ServiceLogging;
+import org.glassfish.security.services.spi.authorization.RoleMappingProvider;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+
+import com.sun.enterprise.util.LocalStringManagerImpl;
+import org.glassfish.logging.annotation.LogMessageInfo;
+
+/**
+ * <code>RoleMappingServiceImpl</code> implements
+ * <code>{@link org.glassfish.security.services.api.authorization.RoleMappingService}</code>
+ * by delegating role mapping decisions to configured
+ * <code>{@link org.glassfish.security.services.spi.RoleMappingProvider}</code>
+ * instances.
+ */
+@Service
+@Singleton
+@Secure(accessPermissionName="security/service/rolemapper")
+public final class RoleMappingServiceImpl implements RoleMappingService, PostConstruct {
+ private static final Level DEBUG_LEVEL = Level.FINER;
+ private static final Logger logger =
+ Logger.getLogger(ServiceLogging.SEC_SVCS_LOGGER,ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+ private static LocalStringManagerImpl localStrings =
+ new LocalStringManagerImpl(RoleMappingServiceImpl.class);
+
+ @Inject
+ private Domain domain;
+
+ @Inject
+ private ServiceLocator serviceLocator;
+
+ // Role Mapping Service Configuration Information
+ private org.glassfish.security.services.config.RoleMappingService config;
+ private RoleMappingProvider provider;
+
+ // Service lifecycle
+ enum InitializationState {
+ NOT_INITIALIZED,
+ SUCCESS_INIT,
+ FAILED_INIT
+ }
+ private volatile InitializationState initialized = InitializationState.NOT_INITIALIZED;
+ private volatile String reasonInitFailed =
+ localStrings.getLocalString("service.role.not_config","The Role Mapping Service was not configured properly.");
+
+ final InitializationState getInitializationState() {
+ return initialized;
+ }
+
+ final String getReasonInitializationFailed() {
+ return reasonInitFailed;
+ }
+
+ final void checkServiceAvailability() {
+ if (InitializationState.SUCCESS_INIT != getInitializationState()) {
+ throw new IllegalStateException(
+ localStrings.getLocalString("service.role.not_avail","The Role Mapping Service is not available.")
+ + getReasonInitializationFailed());
+ }
+ }
+
+ private final List<AzAttributeResolver> attributeResolvers =
+ Collections.synchronizedList(new java.util.ArrayList<AzAttributeResolver>());
+
+ private boolean isDebug() {
+ return logger.isLoggable(DEBUG_LEVEL);
+ }
+
+ // Helpers
+ private AzSubject makeAzSubject(final Subject subject) {
+ AzSubject azs = new AzSubjectImpl(subject);
+ return azs;
+ }
+
+ private AzResource makeAzResource(final URI resource) {
+ AzResource azr = new AzResourceImpl(resource);
+ return azr;
+ }
+
+ /**
+ * Initialize the Role Mapping service with the configured role mapping provider.
+ */
+ @Override
+ public void initialize(SecurityConfiguration securityServiceConfiguration) {
+ if (InitializationState.NOT_INITIALIZED != initialized) {
+ return;
+ }
+ try {
+ // Get the Role Mapping Service configuration
+ config = (org.glassfish.security.services.config.RoleMappingService) securityServiceConfiguration;
+ if (config != null) {
+ // Get the role mapping provider configuration
+ // Consider only one provider for now and take the first provider found!
+ List<SecurityProvider> providersConfig = config.getSecurityProviders();
+ SecurityProvider roleProviderConfig = null;
+ if (providersConfig != null) roleProviderConfig = providersConfig.get(0);
+ if (roleProviderConfig != null) {
+ // Get the provider
+ String providerName = roleProviderConfig.getName();
+ if (isDebug()) {
+ logger.log(DEBUG_LEVEL, "Attempting to get Role Mapping Provider \"{0}\".", providerName );
+ }
+ provider = AccessController.doPrivileged(
+ new PrivilegedLookup<RoleMappingProvider>(serviceLocator, RoleMappingProvider.class, providerName) );
+
+ if (provider == null) {
+ throw new IllegalStateException(localStrings.getLocalString("service.role.not_provider",
+ "Role Mapping Provider {0} not found.", providerName));
+ }
+
+ // Initialize the provider
+ provider.initialize(roleProviderConfig);
+
+ // Service setup complete
+ initialized = InitializationState.SUCCESS_INIT;
+ reasonInitFailed = null;
+
+ // Log initialized
+ logger.log(Level.INFO, ROLEMAPSVC_INITIALIZED);
+ }
+ }
+ } catch (Exception e) {
+ String eMsg = e.getMessage();
+ String eClass = e.getClass().getName();
+ reasonInitFailed = localStrings.getLocalString("service.role.init_failed",
+ "Role Mapping Service initialization failed, exception {0}, message {1}", eClass, eMsg);
+ logger.log(Level.WARNING, ROLEMAPSVC_INIT_FAILED, new Object[] {eClass, eMsg});
+ throw new RuntimeException(reasonInitFailed, e);
+ } finally {
+ if (InitializationState.SUCCESS_INIT != initialized) {
+ initialized = InitializationState.FAILED_INIT;
+ }
+ }
+ }
+
+ /**
+ * Determine the user's role by converting arguments into security authorization data types.
+ *
+ * @see <code>{@link org.glassfish.security.services.api.authorization.RoleMappingService}</code>
+ */
+ @Override
+ public boolean isUserInRole(String appContext, Subject subject, URI resource, String role) {
+ // Validate inputs
+ if (subject == null) throw new IllegalArgumentException(
+ localStrings.getLocalString("service.subject_null", "The supplied Subject is null."));
+ if (resource == null) throw new IllegalArgumentException(
+ localStrings.getLocalString("service.resource_null", "The supplied Resource is null."));
+
+ // Convert arguments
+ return isUserInRole(appContext, makeAzSubject(subject), makeAzResource(resource), role);
+ }
+
+ /**
+ * Determine if the user's is in the specified role.
+ *
+ * @see <code>{@link org.glassfish.security.services.api.authorization.RoleMappingService}</code>
+ */
+ @Override
+ public boolean isUserInRole(String appContext, AzSubject subject, AzResource resource, String role) {
+ boolean result = false;
+
+ // Validate inputs
+ if (subject == null) throw new IllegalArgumentException(
+ localStrings.getLocalString("service.subject_null", "The supplied Subject is null."));
+ if (resource == null) throw new IllegalArgumentException(
+ localStrings.getLocalString("service.resource_null", "The supplied Resource is null."));
+
+ // Make sure provider and config have been setup...
+ checkServiceAvailability();
+
+ // Call provider - AzEnvironment and AzAttributeResolver are placeholders
+ result = provider.isUserInRole(appContext, subject, resource, role, new AzEnvironmentImpl(), attributeResolvers);
+
+ // Display and return results
+ if (isDebug()) {
+ logger.log(DEBUG_LEVEL, "Role Mapping Service result {0}"
+ + " for role {1} with resource {2} using subject {3} in context {4}.",
+ new String[]{ Boolean.toString(result), role,
+ resource.toString(), subject.toString(), appContext});
+ }
+ return result;
+ }
+
+ /**
+ * Find an existing <code>RoleDeploymentContext</code>, or create a new one if one does not
+ * already exist for the specified application context.
+ *
+ * @see <code>{@link org.glassfish.security.services.api.authorization.RoleMappingService}</code>
+ */
+ @Override
+ public RoleMappingService.RoleDeploymentContext findOrCreateDeploymentContext(String appContext) {
+ checkServiceAvailability();
+ return provider.findOrCreateDeploymentContext(appContext);
+ }
+
+ /**
+ * Handle lookup of role mapping service configuration and initialization.
+ * If no service or provider is configured the service run-time will throw exceptions.
+ *
+ * Addresses alternate configuration handling until adopt @Proxiable support.
+ */
+ @Override
+ public void postConstruct() {
+ org.glassfish.security.services.config.RoleMappingService roleConfiguration =
+ ServiceFactory.getSecurityServiceConfiguration(
+ domain, org.glassfish.security.services.config.RoleMappingService.class);
+ initialize(roleConfiguration);
+ }
+
+ //
+ // Log Messages
+ //
+
+ @LogMessageInfo(
+ message = "Role Mapping Service has successfully initialized.",
+ level = "INFO")
+ private static final String ROLEMAPSVC_INITIALIZED = "SEC-SVCS-00150";
+
+ @LogMessageInfo(
+ message = "Role Mapping Service initialization failed, exception {0}, message {1}",
+ level = "WARNING")
+ private static final String ROLEMAPSVC_INIT_FAILED = "SEC-SVCS-00151";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributeImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributeImpl.java
new file mode 100755
index 0000000..1be4012
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributeImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.common;
+
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.Set;
+
+import org.glassfish.security.services.api.common.Attribute;
+
+
+public class AttributeImpl implements Attribute {
+
+ private String name = null;
+ private Set<String> values = new TreeSet<String>();
+
+ protected AttributeImpl() {}
+
+ public AttributeImpl(String name) {
+ this.name = name;
+ }
+
+ public AttributeImpl(String name, String value) {
+ this(name);
+ addValue(value);
+ }
+
+ public AttributeImpl(String name, Set<String> values) {
+ this(name);
+ addValues(values);
+ }
+
+ public AttributeImpl(String name, String[] values) {
+ this(name);
+ addValues(values);
+ }
+
+ public int getValueCount() { return values.size(); }
+
+ public String getName() { return name; }
+
+ public String getValue() {
+ if(getValueCount() == 0) {
+ return null;
+ }
+ Iterator<String> i = values.iterator();
+ return i.next();
+ }
+
+ public Set<String> getValues() { return values; }
+
+ public String[] getValuesAsArray() { return values.toArray(new String[0]); }
+
+ public void addValue(String value) {
+ if (value != null && !value.trim().equals("")) {
+ values.add(value);
+ }
+ }
+
+ public void addValues(Set<String> values) {
+ addValues(values.toArray(new String[0]));
+ }
+
+ public void addValues(String[] values) {
+ for (int i = 0; i < values.length; i++) {
+ addValue(values[i]);
+ }
+ }
+
+ public void removeValue(String value) {
+ values.remove(value);
+ }
+
+ public void removeValues(Set<String> values) {
+ this.values.removeAll(values);
+ }
+
+ public void removeValues(String[] values) {
+ this.values.removeAll(Arrays.asList(values));
+ }
+
+ public void clear() {
+ values.clear();
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributesImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributesImpl.java
new file mode 100755
index 0000000..11dc23e
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/common/AttributesImpl.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.common;
+
+
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.glassfish.security.services.api.common.Attribute;
+import org.glassfish.security.services.api.common.Attributes;
+
+
+public class AttributesImpl implements Attributes {
+
+ private final TreeMap<String, Attribute> attributes;
+
+ public AttributesImpl() {
+ attributes = new TreeMap<String, Attribute>();
+ }
+
+ /**
+ * Copy constructor
+ */
+ public AttributesImpl( AttributesImpl other ) {
+ if ( null == other ) {
+ throw new NullPointerException( "Given illegal null AttributesImpl." );
+ }
+ attributes = new TreeMap<String, Attribute>( other.attributes );
+ }
+
+ public int getAttributeCount() {
+ return attributes.size();
+ }
+
+ public Set<String> getAttributeNames() {
+ return attributes.keySet();
+ }
+
+ public Attribute getAttribute(String name) {
+ return attributes.get(name);
+ }
+
+ public String getAttributeValue(String name) {
+ Attribute a = attributes.get(name);
+ if(a != null) {
+ return a.getValue();
+ }
+ return null;
+ }
+
+ public Set<String> getAttributeValues(String name) {
+ Attribute a = attributes.get(name);
+ if(a != null) {
+ return a.getValues();
+ }
+ return null;
+ }
+
+ public String[] getAttributeValuesAsArray(String name) {
+ Attribute a = attributes.get(name);
+ if(a != null) {
+ return a.getValuesAsArray();
+ }
+ return null;
+ }
+
+ public void addAttribute(String name, String value, boolean replace) {
+ Attribute a = attributes.get(name);
+ if(a != null && !replace) {
+ a.addValue(value);
+ }
+ else {
+ attributes.put(name, new AttributeImpl(name, value));
+ }
+ }
+
+ public void addAttribute(String name, Set<String> values, boolean replace) {
+ Attribute a = attributes.get(name);
+ if(a != null && !replace) {
+ a.addValues(values);
+ }
+ else {
+ attributes.put(name, new AttributeImpl(name, values));
+ }
+ }
+
+ public void addAttribute(String name, String[] values, boolean replace) {
+ Attribute a = attributes.get(name);
+ if(a != null && !replace) {
+ a.addValues(values);
+ }
+ else {
+ attributes.put(name, new AttributeImpl(name, values));
+ }
+ }
+
+ public void removeAttribute(String name) {
+ attributes.remove(name);
+ }
+
+ public void removeAttributeValue(String name, String value) {
+ Attribute a = attributes.get(name);
+ if (a != null) {
+ a.removeValue(value);
+ }
+ }
+
+ public void removeAttributeValues(String name, Set<String> values) {
+ Attribute a = attributes.get(name);
+ if (a != null) {
+ a.removeValues(values);
+ }
+ }
+
+ public void removeAttributeValues(String name, String[] values) {
+ Attribute a = attributes.get(name);
+ if (a != null) {
+ a.removeValues(values);
+ }
+ }
+
+ public void removeAllAttributeValues(String name) {
+ Attribute a = attributes.get(name);
+ if (a != null) {
+ a.clear();
+ }
+ }
+
+ public void clear() {
+ attributes.clear();
+
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/context/SecurityContextServiceImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/context/SecurityContextServiceImpl.java
new file mode 100755
index 0000000..e0f863a
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/impl/context/SecurityContextServiceImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.context;
+
+
+import org.glassfish.security.services.api.common.Attributes;
+import org.glassfish.security.services.api.context.SecurityContextService;
+import org.glassfish.security.services.impl.common.AttributesImpl;
+
+import javax.inject.Singleton;
+import org.jvnet.hk2.annotations.Service;
+
+@Service
+@Singleton
+public class SecurityContextServiceImpl implements SecurityContextService {
+
+ private Attributes envAttributes = new AttributesImpl();
+
+ public Attributes getEnvironmentAttributes() {
+ return envAttributes;
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/AuthorizationProviderConfig.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/AuthorizationProviderConfig.java
new file mode 100644
index 0000000..564dc43
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/AuthorizationProviderConfig.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.provider.authorization;
+
+import java.beans.PropertyVetoException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.security.services.config.SecurityProviderConfig;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.DuckTyped;
+import org.jvnet.hk2.config.Element;
+import org.jvnet.hk2.config.types.Property;
+import org.jvnet.hk2.config.types.PropertyBag;
+
+import com.sun.enterprise.config.serverbeans.customvalidators.JavaClassName;
+
+
+@Configured
+public interface AuthorizationProviderConfig extends SecurityProviderConfig, PropertyBag {
+
+
+ /**
+ * Gets the class name of the authorization provider.
+ */
+ @Attribute(required=false)
+ @NotNull
+ @JavaClassName
+ public String getProviderClass();
+ public void setProviderClass(String value) throws PropertyVetoException;
+
+ /**
+ * Configuration parameter indicating if the provider support policy deploy or not
+ * @return true support policy deploy
+ */
+ @Attribute(defaultValue = "true")
+ boolean getSupportPolicyDeploy();
+ void setSupportPolicyDeploy(boolean value) throws PropertyVetoException;
+
+ /**
+ * configuration parameter to indicate the version of the provider
+ * @return version of the provider
+ */
+ @Attribute(required=false)
+ String getVersion();
+ void setVersion(String value) throws PropertyVetoException;
+
+
+ /**
+ * Gets the properties of the LoginModule.
+ */
+ @Element
+ List<Property> getProperty();
+
+ /**
+ * Gets the options of the LoginModule for use with JAAS Configuration.
+ */
+ @DuckTyped
+ Map<String,?> getProviderOptions();
+
+ class Duck {
+ /**
+ * Gets the options of the LoginModule for use with JAAS Configuration.
+ */
+ public static Map<String,?> getProviderOptions(AuthorizationProviderConfig config) {
+ Map<String,String> providerOptions = new HashMap<String,String>();
+ for (Property prop : config.getProperty()) {
+ providerOptions.put(prop.getName(), prop.getValue());
+ }
+ return providerOptions;
+ }
+ }
+
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/RoleMappingProviderConfig.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/RoleMappingProviderConfig.java
new file mode 100644
index 0000000..4a227a2
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/RoleMappingProviderConfig.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.provider.authorization;
+
+import java.beans.PropertyVetoException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.constraints.NotNull;
+
+import org.glassfish.security.services.config.SecurityProviderConfig;
+
+import org.jvnet.hk2.config.Attribute;
+import org.jvnet.hk2.config.Configured;
+import org.jvnet.hk2.config.DuckTyped;
+import org.jvnet.hk2.config.Element;
+import org.jvnet.hk2.config.types.Property;
+import org.jvnet.hk2.config.types.PropertyBag;
+
+import com.sun.enterprise.config.serverbeans.customvalidators.JavaClassName;
+
+@Configured
+public interface RoleMappingProviderConfig extends SecurityProviderConfig, PropertyBag {
+
+ /**
+ * Gets the class name of the role provider.
+ */
+ @Attribute(required=false)
+ @NotNull
+ @JavaClassName
+ public String getProviderClass();
+ public void setProviderClass(String value) throws PropertyVetoException;
+
+ /**
+ * Indicates if the provider supports role deployment.
+ */
+ @Attribute(defaultValue = "true")
+ boolean getSupportRoleDeploy();
+ void setSupportRoleDeploy(boolean value) throws PropertyVetoException;
+
+ /**
+ * Gets the version of the provider.
+ */
+ @Attribute(required=false)
+ String getVersion();
+ void setVersion(String value) throws PropertyVetoException;
+
+ /**
+ * Gets the properties of the provider.
+ */
+ @Element
+ List<Property> getProperty();
+
+ /**
+ * Gets the options of the provider.
+ */
+ @DuckTyped
+ Map<String,?> getProviderOptions();
+
+ class Duck {
+ /**
+ * Gets the options of the provider by looking at the properties.
+ */
+ public static Map<String,?> getProviderOptions(RoleMappingProviderConfig config) {
+ Map<String,String> providerOptions = new HashMap<String,String>();
+ for (Property prop : config.getProperty()) {
+ providerOptions.put(prop.getName(), prop.getValue());
+ }
+ return providerOptions;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleAuthorizationProviderImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleAuthorizationProviderImpl.java
new file mode 100644
index 0000000..df1d0c4
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleAuthorizationProviderImpl.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.provider.authorization;
+
+import com.sun.enterprise.config.serverbeans.Domain;
+import com.sun.enterprise.config.serverbeans.SecureAdmin;
+import com.sun.enterprise.config.serverbeans.SecureAdminPrincipal;
+import java.net.URI;
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.inject.Inject;
+import org.glassfish.api.admin.ServerEnvironment;
+import org.glassfish.logging.annotation.LogMessageInfo;
+
+import org.glassfish.security.services.api.authorization.*;
+import org.glassfish.security.services.api.authorization.AzResult.Decision;
+import org.glassfish.security.services.api.authorization.AzResult.Status;
+import org.glassfish.security.services.api.authorization.AuthorizationService.PolicyDeploymentContext;
+import org.glassfish.security.services.api.authorization.AuthorizationAdminConstants;
+import org.glassfish.security.services.common.Secure;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.spi.authorization.AuthorizationProvider;
+import org.glassfish.security.services.impl.ServiceLogging;
+import org.glassfish.security.services.impl.authorization.AzResultImpl;
+import org.glassfish.security.services.impl.authorization.AzObligationsImpl;
+
+import org.jvnet.hk2.annotations.Service;
+import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.hk2.api.ServiceLocator;
+
+@Service (name="simpleAuthorization")
+@PerLookup
+@Secure(accessPermissionName = "security/service/authorization/provider/simple")
+public class SimpleAuthorizationProviderImpl implements AuthorizationProvider{
+
+ private final static Level DEBUG_LEVEL = Level.FINER;
+ private static final Logger _logger =
+ Logger.getLogger(ServiceLogging.SEC_PROV_LOGGER,ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+
+ private AuthorizationProviderConfig cfg;
+ private boolean deployable;
+ private String version;
+
+ @Inject
+ private ServerEnvironment serverEnv;
+
+ @Inject
+ private ServiceLocator serviceLocator;
+
+ private Domain domain = null;
+
+ private SecureAdmin secureAdmin = null;
+
+ private Decider decider;
+
+ @Override
+ public void initialize(SecurityProvider providerConfig) {
+
+ cfg = (AuthorizationProviderConfig)providerConfig.getSecurityProviderConfig().get(0);
+ deployable = cfg.getSupportPolicyDeploy();
+ version = cfg.getVersion();
+ domain = serviceLocator.getService(Domain.class);
+ secureAdmin = domain.getSecureAdmin();
+ if (isDebug()) {
+ _logger.log(DEBUG_LEVEL, "provide to do policy deploy: " + deployable);
+ _logger.log(DEBUG_LEVEL, "provide version to use: " + version);
+ }
+ }
+
+ protected Decider createDecider() {
+ return new Decider();
+ }
+
+ private synchronized Decider getDecider() {
+ if (decider == null) {
+ decider = createDecider();
+ if (isDebug()) {
+ _logger.log(DEBUG_LEVEL, "Created SimpleAuthorizationProviderImpl Decider of type {0}", decider.getClass().getName());
+ }
+ }
+ return decider;
+ }
+
+ private boolean isDebug() {
+ return _logger.isLoggable(DEBUG_LEVEL);
+ }
+
+ @Override
+ public AzResult getAuthorizationDecision(
+ AzSubject subject,
+ AzResource resource,
+ AzAction action,
+ AzEnvironment environment,
+ List<AzAttributeResolver> attributeResolvers ) {
+
+ //TODO: get user roles from Rolemapper, and do the policy evaluation
+ if ( ! isAdminResource(resource)) {
+ /*
+ * Log a loud warning if the resource name lacks the correct
+ * scheme, but go ahead anyway and make the authorization decision.
+ */
+ final String resourceName = resource.getUri() == null ? "null" : resource.getUri().toASCIIString();
+ _logger.log(Level.WARNING, ATZPROV_BAD_RESOURCE, resourceName);
+ _logger.log(Level.WARNING, "IllegalArgumentException", new IllegalArgumentException(resourceName));
+ }
+ return getAdminDecision(subject, resource, action, environment);
+ }
+
+ private boolean isAdminResource(final AzResource resource) {
+ final URI resourceURI = resource.getUri();
+ return "admin".equals(resourceURI.getScheme());
+ }
+
+ private AzResult getAdminDecision(
+ final AzSubject subject,
+ final AzResource resource,
+ final AzAction action,
+ final AzEnvironment environment) {
+ if (isDebug()) {
+ _logger.log(DEBUG_LEVEL, "");
+ }
+ AzResult rtn = new AzResultImpl(getDecider().decide(subject, resource, action, environment),
+ Status.OK, new AzObligationsImpl());
+
+ return rtn;
+ }
+
+ @Override
+ public PolicyDeploymentContext findOrCreateDeploymentContext(String appContext) {
+
+ return null;
+ }
+
+ /**
+ * Chooses what authorization decision to render.
+ *
+ * We always require that the user be an administrator, established
+ * (for open-source) by having a Principal with name asadmin.
+ *
+ * Beyond that, there are historical requirements for authenticated admin access:
+ *
+ * - "External" users (CLI, browser, JMX)
+ * - can perform all actions locally on the DAS
+ * - can perform all actions remotely on the DAS if secure admin has been enabled [1]
+ * - JMX users can perform read-only actions on a non-DAS instance,
+ * remotely if secure admin has been enabled and always locally
+ *
+ * - Selected local commands can act locally on the local DAS or local instance
+ * using the local password mechanism (stop-local-instance, for example)
+ *
+ * - A server in the same domain can perform all actions in a local or remote server
+ *
+ * - A client (typically run in a shell created by the DAS) can perform all actions
+ * on a local or remote DAS if it uses the admin token mechanism to authenticate
+ *
+ * [1] Note that any attempted remote access that is not permitted has
+ * already been rejected during authentication.
+ *
+ * For enforcing read-only access we assume that any action other than the literal "read"
+ * makes some change in the system.
+ */
+ protected class Decider {
+
+ protected Decision decide(final AzSubject subject, final AzResource resource,
+ final AzAction action, final AzEnvironment env) {
+ /*
+ * Basically, if the subject has one of the "special" principals
+ * (token, local password, etc.) then we accept it for any action
+ * on the DAS and on instances. Otherwise, it's a person and
+ * we allow full access on the DAS but read-only on instances.
+ */
+ Decision result =
+ isSubjectTrustedForDASAndInstances(subject)
+
+ || // Looks external. Allow full access on DAS, read-only on instance.
+
+ (isSubjectAnAdministrator(subject)
+ && ( serverEnv.isDas()
+ || isActionRead(action)
+ )
+ ) ? Decision.PERMIT : Decision.DENY;
+
+ return result;
+ }
+
+ protected String getAdminGroupName() {
+ return AuthorizationAdminConstants.ADMIN_GROUP;
+ }
+ private boolean isSubjectTrustedForDASAndInstances(final AzSubject subject) {
+ final Set<String> principalNames = new HashSet<String>();
+ for (Principal p : subject.getSubject().getPrincipals()) {
+ principalNames.add(p.getName());
+ }
+ principalNames.retainAll(AuthorizationAdminConstants.TRUSTED_FOR_DAS_OR_INSTANCE);
+ return ! principalNames.isEmpty();
+ }
+
+ private boolean isActionRead(final AzAction action) {
+ return "read".equals(action.getAction());
+ }
+
+ private boolean isSubjectAnAdministrator(final AzSubject subject) {
+ return isPrincipalType(subject, getAdminGroupName()) ||
+ hasSecureAdminPrincipal(subject);
+ }
+
+ private boolean isPrincipalType(final AzSubject subject, final String type) {
+ for (Principal p : subject.getSubject().getPrincipals()) {
+ if (type.equals(p.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean hasSecureAdminPrincipal(final AzSubject subject) {
+ /*
+ * If the subject has a principal with a name that matches a
+ * name in the secure admin principals then it's most likely the
+ * DAS sending a request to an instance, in which case it's
+ * an administrator.
+ */
+ if (secureAdmin == null) {
+ return false;
+ }
+ for (Principal p : subject.getSubject().getPrincipals()) {
+ for (SecureAdminPrincipal sap : secureAdmin.getSecureAdminPrincipal()) {
+ if (sap.getDn().equals(p.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ @LogMessageInfo(
+ message = "Authorization Provider supplied an invalid resource: {0}",
+ level = "WARNING")
+ private static final String ATZPROV_BAD_RESOURCE = "SEC-PROV-00100";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleRoleMappingProviderImpl.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleRoleMappingProviderImpl.java
new file mode 100644
index 0000000..f9ffb3b
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/provider/authorization/SimpleRoleMappingProviderImpl.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.provider.authorization;
+
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.glassfish.hk2.api.PerLookup;
+import org.jvnet.hk2.annotations.Service;
+
+import org.glassfish.security.services.api.authorization.AuthorizationAdminConstants;
+import org.glassfish.security.services.api.authorization.AzAttributeResolver;
+import org.glassfish.security.services.api.authorization.AzEnvironment;
+import org.glassfish.security.services.api.authorization.AzResource;
+import org.glassfish.security.services.api.authorization.AzSubject;
+import org.glassfish.security.services.api.authorization.RoleMappingService;
+import org.glassfish.security.services.common.Secure;
+import org.glassfish.security.services.config.SecurityProvider;
+import org.glassfish.security.services.impl.ServiceLogging;
+import org.glassfish.security.services.spi.authorization.RoleMappingProvider;
+
+import org.glassfish.logging.annotation.LogMessageInfo;
+
+@Service (name="simpleRoleMapping")
+@Secure(accessPermissionName="security/service/rolemapper/provider/simple")
+@PerLookup
+public class SimpleRoleMappingProviderImpl implements RoleMappingProvider {
+ private static final Level DEBUG_LEVEL = Level.FINER;
+ private static final Logger _logger =
+ Logger.getLogger(ServiceLogging.SEC_PROV_LOGGER,ServiceLogging.SHARED_LOGMESSAGE_RESOURCE);
+
+ private static final String ADMIN = "Admin";
+
+ private RoleMappingProviderConfig cfg;
+ private boolean deployable;
+ private String version;
+ private Map<String, ?> options;
+
+ private boolean isDebug() {
+ return _logger.isLoggable(DEBUG_LEVEL);
+ }
+
+ private boolean isAdminResource(AzResource resource) {
+ return "admin".equals(resource.getUri().getScheme());
+ }
+
+ private boolean containsAdminGroup(AzSubject subject) {
+ // Only checking for principal name
+ for (Principal p : subject.getSubject().getPrincipals()) {
+ if (AuthorizationAdminConstants.ADMIN_GROUP.equals(p.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void initialize(SecurityProvider providerConfig) {
+ cfg = (RoleMappingProviderConfig)providerConfig.getSecurityProviderConfig().get(0);
+ deployable = cfg.getSupportRoleDeploy();
+ version = cfg.getVersion();
+ options = cfg.getProviderOptions();
+ if (isDebug()) {
+ _logger.log(DEBUG_LEVEL, "provider deploy: " + deployable);
+ _logger.log(DEBUG_LEVEL, "provider version: " + version);
+ _logger.log(DEBUG_LEVEL, "provider options: " + options);
+ }
+ }
+
+ @Override
+ public boolean isUserInRole(String appContext, AzSubject subject, AzResource resource, String role, AzEnvironment environment, List<AzAttributeResolver> resolvers) {
+ boolean result = false;
+ if (isDebug()) _logger.log(DEBUG_LEVEL, "isUserInRole() - " + role);
+
+ if (!isAdminResource(resource)) {
+ // Log a warning if the resource is not correct
+ final String resourceName = resource.getUri() == null ? "null" : resource.getUri().toASCIIString();
+ _logger.log(Level.WARNING, ROLEPROV_BAD_RESOURCE, resourceName);
+ _logger.log(Level.WARNING, "IllegalArgumentException", new IllegalArgumentException(resourceName));
+ }
+
+ // Only support for admin role
+ if (ADMIN.equals(role)) {
+ result = containsAdminGroup(subject);
+ }
+
+ if (isDebug()) _logger.log(DEBUG_LEVEL, "isUserInRole() - returning " + result);
+ return result;
+ }
+
+ @Override
+ public RoleMappingService.RoleDeploymentContext findOrCreateDeploymentContext(String appContext) {
+ // Not Supported
+ return null;
+ }
+
+ @LogMessageInfo(
+ message = "Role Mapping Provider supplied an invalid resource: {0}",
+ level = "WARNING")
+ private static final String ROLEPROV_BAD_RESOURCE = "SEC-PROV-00150";
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/SecurityProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/SecurityProvider.java
new file mode 100644
index 0000000..1d44576
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/SecurityProvider.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.spi;
+
+/**
+ * Base interface used by all security providers
+ */
+public interface SecurityProvider {
+ /**
+ * Initialize the security provider instance with the specific security provider configuration.
+ */
+ public void initialize(org.glassfish.security.services.config.SecurityProvider providerConfig);
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreException.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreException.java
new file mode 100755
index 0000000..a821cc3
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.spi.authentication;
+
+import java.security.GeneralSecurityException;
+
+public class UserStoreException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 2747414489750791081L;
+
+
+ public UserStoreException(String msg) {
+ super(msg);
+ }
+
+ public UserStoreException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreProvider.java
new file mode 100755
index 0000000..b7c126a
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authentication/UserStoreProvider.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.spi.authentication;
+
+import java.util.Set;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.glassfish.security.services.api.common.Attributes;
+
+/*
+ * Provider interface for authentication service.
+ */
+
+public interface UserStoreProvider {
+
+ /*
+ * Represents a user entry in the store
+ */
+ public interface UserEntry {
+ public String getName();
+ public String getDN();
+ public String getUid();
+ public String getStoreId();
+ public Set<GroupEntry> getGroups();
+ public Attributes getAttributes();
+ }
+
+ /*
+ * Represents a group entry in the store
+ */
+ public interface GroupEntry {
+ public String getName();
+ public String getDN();
+ public String getUid();
+ public String getStoreId();
+ public Set<String> getMembers();
+ }
+
+ /*
+ * Page-able Result Set
+ */
+ public interface ResultSet<T> {
+ public boolean hasNext();
+ public T getNext();
+ public void close();
+ }
+
+ /**
+ * Get the unique store ID for this user store. This value must be unique across all
+ * stores configured into the system or which might be propogated into the system via
+ * SSO, etc. If this USP aggregates multiple underlying stores, the user IDs returned
+ * by the provider must be sufficient to uniquely identify users across all of the
+ * underlying stores.
+ *
+ * @return The store ID for this USP.
+ */
+ public String getStoreId();
+
+ /**
+ * Determine if authentication is supported and enabled by this USP.
+ *
+ * @return True or false.
+ */
+ public boolean isAuthenticationEnabled();
+
+ /**
+ * Determine if user lookup is supported and enabled by this USP.
+ *
+ * @return True or false.
+ */
+ public boolean isUserLookupEnabled();
+
+ /**
+ * Determine if user update (CRUD operations) is supported and enabled by this USP.
+ *
+ * @return True or false.
+ */
+ public boolean isUserUpdateEnabled();
+
+ /**
+ * Authenticate using credentials supplied in the given CallbackHandler. All USPs must support
+ * at least NameCallback and PasswordCallback. The only other callback type expected to be commonly
+ * used is X509Certificate, but it's possible to imagine, e.g., KerberosToken or PasswordDigest.
+ *
+ * @param cbh
+ * @param isGetGroups Whether or not to return the user's groups.
+ * @param attributeNames Names of attributes to return, or null for no attributes.
+ * @return If successful, a UserEntry representing the authenticated user, otherwise throws an exception.
+ * @throws LoginException
+ */
+ public UserEntry authenticate(CallbackHandler cbh, boolean isGetGroups, Set<String> attributeNames) throws LoginException;
+
+ /*
+ * User Lookup
+ */
+
+ /**
+ * Lookup users by name. Since name is not necessarily unique, more than one entry may be returned.
+ * Group membership and selected attributes can also be requested, but requesting these may be inefficient
+ * if more than one user is matched.
+ *
+ * @param name The user name to searech for.
+ * @param isGetGroups Whether or not to return users' groups.
+ * @param attributeNames Names of attributes to return, or null for no attributes.
+ * @return The Set of UserEntrys found.
+ *
+ * @throws UserStoreException
+ */
+ public ResultSet<UserEntry> lookupUsersByName(String name, boolean isGetGroups, Set<String> attributeNames) throws UserStoreException;
+
+ /**
+ * Lookup a user by unique ID. Returns the corresponding UserEntry if found.
+ * Group membership and selected attributes can also be requested.
+ *
+ * @param uid
+ * @param isGetGroups Whether or not to return users' groups.
+ * @param attributeNames Names of attributes to return, or null for no attributes.
+ * @return The UserEntry (if found).
+ *
+ * @throws UserStoreException
+ */
+ public UserEntry lookupUserByUid(String uid, boolean isGetGroups, Set<String> attributeNames) throws UserStoreException;
+
+ /*
+ * Group Lookup
+ */
+
+ /**
+ * Get the GroupEntry(s) for the specified group name.
+ *
+ * @param name The name to search on, may include wildcards (e.g., a*, *b, etc.)
+ * @return ResultSet of the GroupEntries matching the specified name.
+ *
+ * @throws UserStoreException
+ */
+ public ResultSet<GroupEntry> lookupGroupsByName(String name) throws UserStoreException;
+
+ /**
+ * Get the GroupEntry for the specified group.
+ *
+ * @param uid The UID of the group to return.
+ * @return GroupEntry corresponding to the group UID.
+ *
+ * @throws UserStoreException
+ */
+ public GroupEntry lookupGroupByUid(String uid) throws UserStoreException;
+
+ /*
+ * User CRUD
+ */
+
+ /**
+ * Create a new user and return the unique ID assigned.
+ *
+ * @param name Name of the new user entry.
+ * @param pwd Password to set on the new entry.
+ * @param attributes Attributes to set on the entry (or null if none).
+ * @return Returns the UID assigned to the new entry (can be used for subsequent operations)
+ *
+ * @throws UserStoreException
+ */
+ public String /*uid*/ createUser(String name, char[] pwd, Attributes attributes) throws UserStoreException;
+
+ /**
+ * Remove the specified user.
+ *
+ * @param uid UID of the user to remove.
+ *
+ * @throws UserStoreException
+ */
+ public void deleteUser(String uid) throws UserStoreException;
+
+ /**
+ * Change the password for the specified user. If old password is provided, verify before changing.
+ *
+ * @param uid UID of user whose password should be changed.
+ * @param oldPwd Old password, if verification desired, or null. If provided, must be valid.
+ * @param newPwd New password to set.
+ *
+ * @throws UserStoreException
+ */
+ public void changePassword(String uid, char[] oldPwd, char[] newPwd) throws UserStoreException; // setPassword(String uid, char[] pwd)? password reset?
+
+ /**
+ * Add the given attribute values to the user entry.
+ *
+ * @param uid
+ * @param attributes
+ * @param replace
+ * @throws UserStoreException
+ */
+ public void addAttributeValues(String uid, Attributes attributes, boolean replace) throws UserStoreException;
+
+ /**
+ * Remove the given attribute values from the user entry.
+ *
+ * @param uid
+ * @param attributes
+ * @throws UserStoreException
+ */
+ public void removeAttributeValues(String uid, Attributes attributes) throws UserStoreException;
+
+ /**
+ * Remove the given attributes from the user entry.
+ *
+ * @param uid
+ * @param attributeNames
+ * @throws UserStoreException
+ */
+ public void removeAttributes(String uid, Set<String> attributeNames) throws UserStoreException;
+
+ /*
+ * Group CRUD
+ */
+
+ /**
+ * Create a new group.
+ *
+ * @param groupName
+ * @return The UID for the newly created group
+ * @throws UserStoreException
+ */
+ public String /*uid*/ createGroup(String groupName) throws UserStoreException;
+
+ /**
+ * Delete a group.
+ *
+ * @param uid UID of group to delete.
+ * @throws UserStoreException
+ */
+ public void deleteGroup(String uid) throws UserStoreException;
+
+ /**
+ * Add the specified user to the set of groups.
+ *
+ * @param uid
+ * @param groups
+ * @throws UserStoreException
+ */
+ public void addUserToGroups(String uid, Set<String> groups) throws UserStoreException;
+
+ /**
+ * Remove the specified user from the set of groups.
+ *
+ * @param uid
+ * @param groups
+ * @throws UserStoreException
+ */
+ public void removeUserFromGroups(String uid, Set<String> groups) throws UserStoreException;
+
+ /**
+ * Add the set of users to the specified group.
+ *
+ * @param uids
+ * @param group
+ * @throws UserStoreException
+ */
+ public void addUsersToGroup(Set<String> uids, String group) throws UserStoreException;
+
+ /**
+ * Remove the set of users from the specified group.
+ *
+ * @param uids
+ * @param group
+ * @throws UserStoreException
+ */
+ public void removeUsersFromGroup(Set<String> uids, String group) throws UserStoreException;
+
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/AuthorizationProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/AuthorizationProvider.java
new file mode 100644
index 0000000..bc216b7
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/AuthorizationProvider.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.spi.authorization;
+
+import org.glassfish.security.services.api.authorization.*;
+import org.glassfish.security.services.spi.SecurityProvider;
+
+import org.jvnet.hk2.annotations.Contract;
+
+import java.util.List;
+
+/**
+ * <code>AuthorizationProvider</code> instances are used by a
+ * <code>{@link org.glassfish.security.services.api.authorization.AuthorizationService}</code>
+ * to make access authorization decisions. This is part of a plug-in mechanism,
+ * which allows access decisions to deferred to an configured implementation.
+ */
+@Contract
+public interface AuthorizationProvider extends SecurityProvider {
+
+
+ /**
+ * Evaluates the specified subject, resource, action, and environment against the body of
+ * policy managed by this provider and returns an access control result.
+ *
+ * @param subject The attributes collection representing the Subject for which an authorization
+ * decision is requested.
+ * @param resource The attributes collection representing the resource for which access is
+ * being requested.
+ * @param action The attributes collection representing the action, with respect to the resource,
+ * for which access is being requested. A null action is interpreted as all
+ * actions, however all actions may also be represented by the AzAction instance.
+ * See <code>{@link org.glassfish.security.services.api.authorization.AzAction}</code>.
+ * @param environment The attributes collection representing the environment, or context,
+ * in which the access decision is being requested, null if none.
+ * @param attributeResolvers The ordered list of attribute resolvers, for
+ * run time determination of missing attributes, null if none.
+ * @return The AzResult indicating the result of the access decision.
+ * @throws IllegalArgumentException Given null or illegal subject or resource
+ * @throws IllegalStateException Provider was not initialized.
+ * @see AuthorizationService#getAuthorizationDecision
+ */
+ AzResult getAuthorizationDecision(
+ AzSubject subject,
+ AzResource resource,
+ AzAction action,
+ AzEnvironment environment,
+ List<AzAttributeResolver> attributeResolvers );
+
+
+ /**
+ * Finds an existing PolicyDeploymentContext, or create a new one if one does not
+ * already exist for the specified appContext. The context will be returned in
+ * an "open" state, and will stay that way until commit() or delete() is called.
+ *
+ * @param appContext The application context for which the PolicyDeploymentContext
+ * is desired.
+ * @return The resulting PolicyDeploymentContext,
+ * null if this provider does not support this feature.
+ * @throws IllegalStateException Provider was not initialized, if this method is supported.
+ * @see AuthorizationService#findOrCreateDeploymentContext(String)
+ */
+ AuthorizationService.PolicyDeploymentContext findOrCreateDeploymentContext(
+ String appContext);
+}
diff --git a/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/RoleMappingProvider.java b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/RoleMappingProvider.java
new file mode 100644
index 0000000..c98919f
--- /dev/null
+++ b/nucleus/security/services/src/main/java/org/glassfish/security/services/spi/authorization/RoleMappingProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.spi.authorization;
+
+import java.util.List;
+
+import org.glassfish.security.services.api.authorization.AzAttributeResolver;
+import org.glassfish.security.services.api.authorization.AzEnvironment;
+import org.glassfish.security.services.api.authorization.AzResource;
+import org.glassfish.security.services.api.authorization.AzSubject;
+import org.glassfish.security.services.api.authorization.RoleMappingService;
+import org.glassfish.security.services.spi.SecurityProvider;
+
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * <code>RoleMappingProvider</code> instances are used by the
+ * <code>{@link org.glassfish.security.services.api.authorization.RoleMappingService}</code>
+ * to evaluate role policy conditions.
+ *
+ * The security provider is part of a plug-in mechanism which allows decisions
+ * to be handled by a configured implementation.
+ */
+@Contract
+public interface RoleMappingProvider extends SecurityProvider {
+
+ /**
+ * Determine whether the user (<code>AzSubject</code>) has the indicated role
+ * for a given resource (<code>AzResource</code>) and application context.
+ *
+ * @param appContext The application context for the query (can be null).
+ * @param subject The target <code>Subject</code>.
+ * @param resource The <code>URI</code> resource for the query.
+ * @param role The target role.
+ * @param environment The attributes collection representing the environment.
+ * @param attributeResolvers The ordered list of attribute resolvers.
+ *
+ * @see {@link org.glassfish.security.services.api.authorization.RoleMappingService#isUserInRole(String, AzSubject, AzResource, String)}
+ */
+ public boolean isUserInRole(String appContext,
+ AzSubject subject,
+ AzResource resource,
+ String role,
+ AzEnvironment environment,
+ List<AzAttributeResolver> attributeResolvers);
+
+ /**
+ * Find an existing <code>RoleDeploymentContext</code>, or create a new one if one does not
+ * already exist for the specified application context.
+ *
+ * @param appContext The application context for which the <code>RoleDeploymentContext</code> is desired.
+ *
+ * @see {@link org.glassfish.security.services.api.authorization.RoleMappingService#findOrCreateDeploymentContext(String)}
+ */
+ public RoleMappingService.RoleDeploymentContext findOrCreateDeploymentContext(String appContext);
+}
diff --git a/nucleus/security/services/src/main/resources/org/glassfish/security/services/commands/LocalStrings.properties b/nucleus/security/services/src/main/resources/org/glassfish/security/services/commands/LocalStrings.properties
new file mode 100644
index 0000000..b5cf654
--- /dev/null
+++ b/nucleus/security/services/src/main/resources/org/glassfish/security/services/commands/LocalStrings.properties
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+#LDAP Admin Access
+ldap.ok=LDAP server at {0} is accessible.
+ldap.na=LDAP server at {0} could not be accessed. Exception {1} was thrown with this message: {2}.
+ldap.realm.setup=The LDAP Auth Realm {0} was configured correctly in admin server''s configuration.
+config.to.ldap=Auth Realm named {0} will be configured for given LDAP. Any existing realm with that name will be renamed to {1}. The renamed auth realm can be removed.
+ldap.noExistingAtnProvider=This command modifies the authentication service provider named {0} but no such provider is configured.
+ldap.noExistingAtnService=This command modifies the authentication service named {0} but no such service is configured.
+ldap.fileRealmProviderNotLoginModuleType=The file realm provider {0} exists in the service {1} but must be of type LoginModule and is of type {2} instead.
+ldap.authProviderConfigOK=The authentication service provider {0} was reconfigured correctly.
+ldap.noAuthProviderConfig=The authentication service provider {0} must contain a LoginModule config named {1} but did not.
diff --git a/nucleus/security/services/src/main/resources/org/glassfish/security/services/impl/authorization/LocalStrings.properties b/nucleus/security/services/src/main/resources/org/glassfish/security/services/impl/authorization/LocalStrings.properties
new file mode 100644
index 0000000..a83dc29
--- /dev/null
+++ b/nucleus/security/services/src/main/resources/org/glassfish/security/services/impl/authorization/LocalStrings.properties
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+service.subject_null=The supplied Subject is null.
+service.resource_null=The supplied Resource is null.
+service.permission_null=The supplied Permission is null.
+service.resolver_null=The supplied Attribute Resolver is null.
+
+service.role.init_failed=Role Mapping Service initialization failed, exception {0}, message {1}
+service.role.not_avail=The Role Mapping Service is not available.
+service.role.not_config=The Role Mapping Service was not configured properly.
+service.role.not_provider=Role Mapping Provider {0} not found.
+
+service.atz.init_failed=Authorization Service initialization failed, exception {0}, message {1}
+service.atz.not_avail=The Authorization service is not available.
+service.atz.never_init=Authorization Service never initialized.
+service.atz.not_config=The Authorization service is not configured in the domain configuration file.
+service.atz.no_prov_config=No provider configured for the Authorization service in the domain configuration file.
+service.atz.not_provider=Authorization Provider {0} not found.
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleAtzProviderTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleAtzProviderTest.java
new file mode 100644
index 0000000..362d6e4
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleAtzProviderTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+
+import org.glassfish.security.services.impl.authorization.*;
+import java.net.URI;
+
+import javax.security.auth.Subject;
+import org.glassfish.security.common.PrincipalImpl;
+import org.glassfish.security.services.api.common.Attributes;
+import org.glassfish.security.services.api.context.SecurityContextService;
+import org.glassfish.security.services.impl.authorization.AuthorizationServiceImpl;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.jvnet.hk2.testing.junit.HK2Runner;
+
+import org.glassfish.security.services.spi.authorization.AuthorizationProvider;
+
+public class SimpleAtzProviderTest extends HK2Runner {
+
+ private AuthorizationProvider simpleAtzPrv = null;
+ private SecurityContextService contextService = null;
+
+
+ @Before
+ public void before() {
+ super.before();
+
+ String pf = System.getProperty("java.security.policy");
+ System.out.println("policy file = " + pf);
+ String bd = System.getProperty("build.dir");
+ System.out.println("build dir = " + bd);
+
+ String apsd = System.getProperty("appserver_dir");
+ System.out.println("appserver dir = " + apsd);
+
+ String local = System.getProperty("localRepository");
+ System.out.println("local repository dir = " + local);
+
+ simpleAtzPrv = testLocator.getService(AuthorizationProvider.class, "simpleAuthorization");
+ contextService = testLocator.getService(SecurityContextService.class);
+
+ Assert.assertNotNull(simpleAtzPrv);
+ Assert.assertNotNull(contextService);
+
+ contextService.getEnvironmentAttributes().addAttribute(
+ AuthorizationAdminConstants.ISDAS_ATTRIBUTE, "true", true);
+ }
+
+ @Test
+ public void testService() throws Exception {
+ final AuthorizationService authorizationService = new AuthorizationServiceImpl();
+ Assert.assertNotNull(simpleAtzPrv);
+ final AzEnvironment env = new AzEnvironmentImpl();
+ final Attributes attrs = contextService.getEnvironmentAttributes();
+ for (String attrName : attrs.getAttributeNames()) {
+ env.addAttribute(attrName, attrs.getAttributeValue(attrName), true);
+ }
+ AzSubject azS = authorizationService.makeAzSubject(adminSubject());
+ AzResult rt = simpleAtzPrv.getAuthorizationDecision(
+ azS,
+ authorizationService.makeAzResource(URI.create("admin://some/path")),
+ authorizationService.makeAzAction("read"),
+ env,
+ null
+ );
+
+ AzResult.Decision ds = rt.getDecision();
+
+ Assert.assertEquals(AzResult.Decision.PERMIT, ds);
+
+ }
+
+ private Subject adminSubject() {
+ final Subject result = new Subject();
+ result.getPrincipals().add(new PrincipalImpl("asadmin"));
+ return result;
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleRoleProviderTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleRoleProviderTest.java
new file mode 100644
index 0000000..b2e3c8f
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/api/authorization/SimpleRoleProviderTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.api.authorization;
+
+import java.net.URI;
+import javax.security.auth.Subject;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.jvnet.hk2.testing.junit.HK2Runner;
+
+import org.glassfish.security.common.Group;
+import org.glassfish.security.common.PrincipalImpl;
+import org.glassfish.security.services.impl.authorization.AuthorizationServiceImpl;
+import org.glassfish.security.services.spi.authorization.RoleMappingProvider;
+
+
+public class SimpleRoleProviderTest extends HK2Runner {
+
+ private AuthorizationService authorizationService = new AuthorizationServiceImpl();
+ private RoleMappingProvider simpleRoleProvider = null;
+
+ @Before
+ public void before() {
+ super.before();
+
+ simpleRoleProvider = testLocator.getService(RoleMappingProvider.class, "simpleRoleMapping");
+ }
+
+ @Test
+ public void testProviderAdmin() throws Exception {
+ Assert.assertNotNull(simpleRoleProvider);
+ boolean result = simpleRoleProvider.isUserInRole(null,
+ authorizationService.makeAzSubject(adminSubject()),
+ authorizationService.makeAzResource(URI.create("admin://my/respath")),
+ "Admin", null, null);
+ Assert.assertEquals(true, result);
+ }
+
+ private Subject adminSubject() {
+ Subject result = new Subject();
+ result.getPrincipals().add(new PrincipalImpl("admin"));
+ result.getPrincipals().add(new Group("asadmin"));
+ return result;
+ }
+
+ @Test
+ public void testProviderNonAdmin() throws Exception {
+ Assert.assertNotNull(simpleRoleProvider);
+ boolean result = simpleRoleProvider.isUserInRole(null,
+ authorizationService.makeAzSubject(nonAdminSubject()),
+ authorizationService.makeAzResource(URI.create("admin://negative")),
+ "Admin", null, null);
+ Assert.assertEquals(false, result);
+ }
+
+ private Subject nonAdminSubject() {
+ Subject result = new Subject();
+ result.getPrincipals().add(new PrincipalImpl("joe"));
+ result.getPrincipals().add(new Group("myGroup"));
+ return result;
+ }
+
+ @Test
+ public void testProviderNonAdminRole() throws Exception {
+ Assert.assertNotNull(simpleRoleProvider);
+ boolean result = simpleRoleProvider.isUserInRole(null,
+ authorizationService.makeAzSubject(adminSubject()),
+ authorizationService.makeAzResource(URI.create("foo://other")), // Warning Message
+ "otherRole", null, null);
+ Assert.assertEquals(false, result);
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SecurePermTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SecurePermTest.java
new file mode 100644
index 0000000..e89f00d
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SecurePermTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import java.security.Permission;
+
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SecurePermTest {
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testEqualsObject() {
+
+
+ Permission perm1 = new SecureServiceAccessPermission("a/b/c", "read,write");
+
+ Permission perm2 = new SecureServiceAccessPermission("a/b/c/d", "read,write");
+ Assert.assertFalse(perm1.equals(perm2));
+
+ Permission p3 = null;
+ Assert.assertFalse(perm1.equals(p3));
+
+
+ Permission p5 = new SecureServiceAccessPermission("a/b/c");
+ Assert.assertFalse(perm1.equals(p5));
+ }
+
+ @Test
+ public void testEquals1() {
+ Permission p1 = new SecureServiceAccessPermission("a/b/c", "read,write");
+ Permission p2 = new SecureServiceAccessPermission("a/b/c/", "read,write");
+ Assert.assertFalse(p1.equals(p2));
+ Assert.assertFalse(p1.implies(p2));
+
+ }
+
+ @Test
+ public void testImpliesPermission() {
+ Permission p1 = new SecureServiceAccessPermission("a", "read");
+ Permission p2 = new SecureServiceAccessPermission("b", "read");
+ Assert.assertFalse(p1.implies(p2));
+
+ Permission p3 = new SecureServiceAccessPermission("a", "read,write");
+ Assert.assertTrue(p3.implies(p1));
+ }
+
+ @Test
+ public void testImpliesWild() {
+ Permission p1 = new SecureServiceAccessPermission("a/*", "read");
+
+ Permission p2 = new SecureServiceAccessPermission("a/b", "read");
+ Assert.assertTrue(p1.implies(p2));
+
+ Permission p3 = new SecureServiceAccessPermission("a/b/c", "read");
+ Assert.assertTrue(p1.implies(p3));
+
+
+ Permission p11 = new SecureServiceAccessPermission("a/b/*", "read");
+ Assert.assertTrue(p11.implies(p3));
+
+ Assert.assertFalse(p11.implies(p1));
+ Assert.assertFalse(p11.implies(p2));
+
+ Assert.assertTrue(p11.implies(p11));
+ }
+
+ @Test
+ public void testImpliesWild1() {
+ Permission p1 = new SecureServiceAccessPermission("a/*", null);
+ Permission p2 = new SecureServiceAccessPermission("a/default", null);
+ Assert.assertTrue(p1.implies(p2));
+ }
+
+ @Test
+ public void testImpliesActions() {
+ Permission p1 = new SecureServiceAccessPermission("a", "read,write");
+ Permission p2 = new SecureServiceAccessPermission("a", "read");
+ Assert.assertTrue(p1.implies(p2));
+
+ Permission p3 = new SecureServiceAccessPermission("a", "write");
+ Assert.assertTrue(p1.implies(p3));
+ }
+
+
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SubjectUtilTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SubjectUtilTest.java
new file mode 100644
index 0000000..1014937
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/common/SubjectUtilTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.common;
+
+import org.junit.Test;
+import javax.security.auth.Subject;
+
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.glassfish.security.common.PrincipalImpl;
+
+import junit.framework.Assert;
+
+public class SubjectUtilTest {
+
+ private static final String USERNAME = "john";
+ private static final String USERNAME2 = "John";
+ private static final String[] GROUPS = {"g1", "g2"};
+
+ private boolean debug = false;
+
+ @Test
+ public void testUserNameUtil() {
+
+ Subject sub = createSub(USERNAME, GROUPS);
+
+ List<String> usernames = SubjectUtil.getUsernamesFromSubject(sub);
+
+ if (debug)
+ System.out.println("user list =" + usernames);
+
+ Assert.assertEquals(1, usernames.size());
+ }
+
+
+ @Test
+ public void testGroupNameUtil() {
+
+ Subject sub = createSub(USERNAME, GROUPS);
+
+ List<String> groupnames = SubjectUtil.getGroupnamesFromSubject(sub);
+
+ if (debug)
+ System.out.println("group list =" + groupnames);
+
+ Assert.assertEquals(2, groupnames.size());
+ }
+
+ @Test
+ public void testUserNameUtil_empty() {
+
+ Subject sub = createSub(null, GROUPS);
+
+ List<String> usernames = SubjectUtil.getUsernamesFromSubject(sub);
+
+ Assert.assertEquals(0, usernames.size());
+ }
+
+
+ @Test
+ public void testGroupNameUtil_empty() {
+
+ Subject sub = createSub(USERNAME, null);
+
+ List<String> groupnames = SubjectUtil.getGroupnamesFromSubject(sub);
+
+ Assert.assertEquals(0, groupnames.size());
+
+ }
+
+ @Test
+ public void testUserNameUtil_multi() {
+
+ Subject sub = createSub(USERNAME, GROUPS);
+ sub.getPrincipals().add(new PrincipalImpl(USERNAME2));
+
+ List<String> usernames = SubjectUtil.getUsernamesFromSubject(sub);
+
+ if (debug)
+ System.out.println("user list =" + usernames);
+
+ Assert.assertEquals(2, usernames.size());
+ }
+
+
+
+ public static Subject createSub(String username, String[] groups) {
+
+ Set<Principal> pset = new HashSet<Principal>();
+
+ if (username != null) {
+ Principal u = new PrincipalImpl(username);
+ pset.add(u);
+ }
+
+ if (groups != null) {
+ for (String g : groups) {
+ if (g != null) {
+ Principal p = new org.glassfish.security.common.Group(g);
+ pset.add(p);
+ }
+ }
+ }
+
+
+ Set prvSet = new HashSet();
+
+ Set<Object> pubSet = new HashSet<Object>();
+
+ Subject sub = new Subject(false, pset, pubSet, prvSet);
+
+ return sub;
+
+ }
+
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/PasswordAliasTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/PasswordAliasTest.java
new file mode 100644
index 0000000..eae816c
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/PasswordAliasTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import org.glassfish.api.admin.PasswordAliasStore;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ * @author tjquinn
+ */
+public class PasswordAliasTest {
+
+ private static final char[] TEST_STORE_PW = "dontChangeIt".toCharArray();
+
+ private static File storeFile;
+ private static PasswordAliasStore store;
+
+ @BeforeClass
+ public static void createStore() throws Exception {
+ storeFile = File.createTempFile("pwAliasStore", "jks");
+ final KeyStore ks = KeyStore.getInstance("JCEKS");
+ ks.load(null, TEST_STORE_PW);
+ final OutputStream os = new BufferedOutputStream(new FileOutputStream(storeFile));
+ ks.store(os, TEST_STORE_PW);
+ os.close();
+
+ store = JCEKSPasswordAliasStore.newInstance(storeFile.getAbsolutePath(), TEST_STORE_PW);
+
+ System.out.println("Created temporary store " + storeFile.getAbsolutePath());
+ }
+
+ @AfterClass
+ public static void deleteStore() throws Exception {
+ if ( ! storeFile.delete()) {
+ throw new IOException("Error cleaning up test alias store file " + storeFile.getAbsolutePath());
+ }
+ }
+
+ @Test
+ public void checkShortPW() {
+ checkStoreAndGetPWByAlias("aliasFoo", "123456");
+ }
+
+ @Test
+ public void checkLongPW() {
+ checkStoreAndGetPWByAlias("aliasBar", "12345678901234567890");
+ }
+
+ private void checkStoreAndGetPWByAlias(final String alias, final String pw) {
+ store.put(alias, pw.toCharArray());
+ final String retrievedPW = new String(store.get(alias));
+ Assert.assertEquals("Retrieved password failed to match stored password",
+ getBytesInHex(pw.getBytes()),
+ getBytesInHex(retrievedPW.getBytes()));
+ }
+
+ private static String getBytesInHex(final byte[] bytes) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b: bytes) {
+ sb.append(String.format("%02X", b));
+ }
+ return sb.toString();
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImplTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImplTest.java
new file mode 100644
index 0000000..d7ad9b0
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AuthorizationServiceImplTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.authorization.*;
+import org.glassfish.security.services.api.common.Attribute;
+import org.glassfish.security.services.impl.common.AttributeImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.security.auth.Subject;
+import java.net.URI;
+import java.security.AllPermission;
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.Assert.*;
+import static org.glassfish.security.services.impl.authorization.AuthorizationServiceImpl.InitializationState.*;
+
+/**
+ * @see AuthorizationServiceImpl
+ */
+public class AuthorizationServiceImplTest {
+ private AuthorizationServiceImpl impl;
+
+
+ @Before
+ public void setUp() throws Exception {
+ impl = new AuthorizationServiceImpl();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ impl = null;
+ }
+
+ @Test
+ public void testInitialize() throws Exception {
+
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+
+ try {
+ impl.initialize(null);
+ fail( "Expected initialize to fail." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame( "FAILED_INIT", FAILED_INIT, impl.getInitializationState() );
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testIsPermissionGranted() throws Exception {
+
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+
+ // Does not require service initialization
+ impl.isPermissionGranted( new Subject(), new AllPermission() );
+ }
+
+ @Test
+ public void testIsAuthorized() throws Exception {
+
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+
+ try {
+ impl.isAuthorized(
+ new Subject(),
+ new URI( "admin:///tenants/tenant/mytenant" ),
+ "update" );
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testGetAuthorizationDecision() throws Exception {
+
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+
+ try {
+ impl.getAuthorizationDecision(
+ new AzSubjectImpl( new Subject() ),
+ new AzResourceImpl( new URI( "admin:///tenants/tenant/mytenant" ) ),
+ new AzActionImpl( "update" ) );
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testMakeAzSubject() throws Exception {
+ try {
+ impl.makeAzSubject(null);
+ fail( "Expected fail with null." );
+ } catch ( IllegalArgumentException e ) {
+ }
+
+ Subject s = new Subject();
+ assertSame("Subject", s, impl.makeAzSubject(s).getSubject());
+ }
+
+ @Test
+ public void testMakeAzResource() throws Exception {
+ try {
+ impl.makeAzResource(null);
+ fail( "Expected fail with null." );
+ } catch ( IllegalArgumentException e ) {
+ }
+
+ URI u = new URI( "admin:///" );
+ assertSame("URI", u, impl.makeAzResource(u).getUri());
+ }
+
+ @Test
+ public void testMakeAzAction() throws Exception {
+ AzAction azAction;
+
+ azAction = impl.makeAzAction( null );
+ assertNotNull( azAction );
+ assertNull( "Null", azAction.getAction() );
+
+
+ String action = "update";
+ azAction = impl.makeAzAction( action );
+ assertNotNull(azAction);
+ assertEquals("action", action, azAction.getAction());
+ }
+
+ @Test
+ public void testFindOrCreateDeploymentContext() throws Exception {
+
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+
+ try {
+ impl.findOrCreateDeploymentContext("foo");
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull("getReasonInitializationFailed", impl.getReasonInitializationFailed());
+ }
+
+ @Test
+ public void testAttributeResolvers() throws Exception {
+ assertEquals( "initial", 0 , impl.getAttributeResolvers().size() );
+
+ final AzAttributeResolver testAr1 = new TestAttributeResolver( new AttributeImpl("1") );
+ final AzAttributeResolver testAr2 = new TestAttributeResolver( new AttributeImpl("2") );
+
+ assertTrue( "append 1", impl.appendAttributeResolver( testAr1 ) );
+ assertFalse( "append 1", impl.appendAttributeResolver( testAr1 ) );
+ assertTrue( "append 2", impl.appendAttributeResolver( testAr2 ) );
+ assertFalse( "append 2", impl.appendAttributeResolver( testAr2 ) );
+
+ List<AzAttributeResolver> arList = impl.getAttributeResolvers();
+ assertEquals( "size after append", 2, arList.size());
+ assertEquals( "append 1", "1", arList.get(0).resolve(null,null,null).getName() );
+ assertEquals( "append 2", "2", arList.get(1).resolve(null,null,null).getName() );
+
+ final AzAttributeResolver testAr3 = new TestAttributeResolver( new AttributeImpl("3") );
+ final AzAttributeResolver testAr4 = new TestAttributeResolver( new AttributeImpl("4") );
+ List<AzAttributeResolver> tempList = new ArrayList<AzAttributeResolver>();
+ tempList.add(testAr3);
+ tempList.add(testAr4);
+ impl.setAttributeResolvers( tempList );
+
+ List<AzAttributeResolver> arList2 = impl.getAttributeResolvers();
+ assertEquals("after get list 2", 2, arList2.size());
+ assertEquals("append 3", "3", arList2.get(0).resolve(null, null, null).getName());
+ assertEquals( "append 4", "4", arList2.get(1).resolve(null,null,null).getName() );
+
+ assertTrue( "removeAllAttributeResolvers", impl.removeAllAttributeResolvers() );
+ assertFalse( "removeAllAttributeResolvers", impl.removeAllAttributeResolvers() );
+
+ assertEquals( "final", 0 , impl.getAttributeResolvers().size() );
+ }
+
+
+ /**
+ * Fake test class
+ */
+ private static class TestAttributeResolver implements AzAttributeResolver {
+
+ final Attribute attr;
+
+ private TestAttributeResolver(Attribute attr) {
+ this.attr = attr;
+ }
+
+ @Override
+ public Attribute resolve(
+ String attributeName,
+ AzAttributes collection,
+ AzEnvironment environment) {
+ return this.attr;
+ }
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzActionImplTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzActionImplTest.java
new file mode 100644
index 0000000..7e2e6ba
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzActionImplTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * @see AzActionImpl
+ */
+public class AzActionImplTest {
+ @Test
+ public void testToString() throws Exception {
+
+ AzActionImpl nullAction = new AzActionImpl(null);
+ assertEquals( "null Action", "*", nullAction.toString() );
+
+ AzActionImpl createAction = new AzActionImpl("create");
+ assertEquals( "non-null Action", "create", createAction.toString() );
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzResourceImplTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzResourceImplTest.java
new file mode 100644
index 0000000..5a4a99d
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/AzResourceImplTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import org.glassfish.security.services.api.common.Attribute;
+import org.glassfish.security.services.api.common.Attributes;
+import org.glassfish.security.services.impl.common.AttributesImpl;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.glassfish.security.services.impl.authorization.AzResourceImpl.addAttributesFromUriQuery;
+import static org.glassfish.security.services.impl.authorization.AzResourceImpl.decodeURI;
+import static junit.framework.Assert.*;
+
+/**
+ * @see AzResourceImpl
+ */
+public class AzResourceImplTest {
+ @Test
+ public void testGetters() throws Exception {
+ URI uri;
+ AzResourceImpl impl;
+
+ // Null
+ try {
+ new AzResourceImpl(null);
+ fail( "Expected exception" );
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Doesn't care about scheme
+ uri = new URI( "http://foo" );
+ impl = new AzResourceImpl(uri);
+ assertSame( "non-admin OK", uri, impl.getUri() );
+
+ // Empty domain (i.e. default)
+ uri = new URI( "admin:///tenants/tenant/zirka?locked=true%3D" );
+ impl = new AzResourceImpl(uri);
+
+ // Test getters
+ assertEquals("URI", uri, impl.getUri());
+ assertEquals("toString", "admin:///tenants/tenant/zirka?locked=true%3D", impl.toString());
+
+ // Non-empty domain, empty path
+ uri = new URI( "admin://myDomain?locked=true%3D" );
+ impl = new AzResourceImpl(uri);
+
+ // Test getters
+ assertEquals("URI", uri, impl.getUri());
+ assertEquals("toString", "admin://myDomain?locked=true%3D", impl.toString());
+ }
+
+ @Test
+ public void testAddAttributesFromUriQuery() throws Exception {
+ URI uri = new URI( "admin:///tenants/tenant/zirka?locked=true" );
+ Attributes attributes = new AttributesImpl();
+ Attribute attribute;
+ Set<String> values;
+ Iterator<String> iter;
+ BitSet bitset;
+
+ final boolean REPLACE = true;
+
+ // Null
+ try {
+ addAttributesFromUriQuery( null, attributes, REPLACE );
+ fail( "Expected IllegalArgumentException from null URI." );
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ addAttributesFromUriQuery( uri, null, REPLACE );
+ fail( "Expected IllegalArgumentException from null Attributes." );
+ } catch (IllegalArgumentException e) {
+ }
+
+ assertEquals( "Empty attributes", 0, attributes.getAttributeCount() );
+
+ // No params
+ uri = new URI( "admin:///tenants/tenant/zirka" );
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals( "Empty attributes", 0, attributes.getAttributeCount() );
+
+ // 1 param
+ uri = new URI( "admin:///tenants/tenant/zirka?name1=value1" );
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals("Attributes count", 1, attributes.getAttributeCount());
+ assertNotNull("attribute", attribute = attributes.getAttribute("name1"));
+ values = attribute.getValues();
+ assertEquals("Values count", 1, values.size());
+ iter = values.iterator();
+ assertTrue( iter.hasNext() );
+ assertEquals("Values value", "value1", iter.next());
+ assertFalse( iter.hasNext() );
+
+ // Repeat, no dup value
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals("Attributes count", 1, attributes.getAttributeCount());
+ assertNotNull("attribute", attribute = attributes.getAttribute("name1"));
+ values = attribute.getValues();
+ assertEquals("Values count", 1, values.size());
+ iter = values.iterator();
+ assertTrue( "iterator", iter.hasNext() );
+ assertEquals("Values value", "value1", iter.next());
+ assertFalse("iterator", iter.hasNext());
+
+ // New value
+ uri = new URI( "admin:///tenants/tenant/boris?name1=value2" );
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals("Attributes count", 1, attributes.getAttributeCount());
+ assertNotNull("attribute", attribute = attributes.getAttribute("name1"));
+ values = attribute.getValues();
+ assertEquals("Values count", 2, values.size());
+ bitset = new BitSet(2);
+ for ( String v : values ) {
+ if ( "value1".equals(v) && !bitset.get(0) ) {
+ bitset.set(0);
+ } else if ( "value2".equals(v) && !bitset.get(1) ) {
+ bitset.set(1);
+ } else {
+ fail( "Unexpected attribute value " + v );
+ }
+ }
+
+ // Replace attribute
+ uri = new URI( "admin:///tenants/tenant/lucky?name1=value3" );
+ addAttributesFromUriQuery( uri, attributes, REPLACE );
+ assertEquals("Attributes count", 1, attributes.getAttributeCount());
+ assertNotNull("attribute", attribute = attributes.getAttribute("name1"));
+ values = attribute.getValues();
+ assertEquals("Values count", 1, values.size());
+ iter = values.iterator();
+ assertTrue( "iterator", iter.hasNext() );
+ assertEquals("Values value", "value3", iter.next());
+ assertFalse("iterator", iter.hasNext());
+
+ // New attribute
+ uri = new URI( "admin:///tenants/tenant/lucky?name2=value21&name2=value22" );
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals("Attributes count", 2, attributes.getAttributeCount());
+ assertNotNull("attribute", attributes.getAttribute("name1"));
+ assertNotNull("attribute", attribute = attributes.getAttribute("name2"));
+ values = attribute.getValues();
+ assertEquals("Values count", 2, values.size());
+ bitset = new BitSet(2);
+ for ( String v : values ) {
+ if ( "value21".equals(v) && !bitset.get(0) ) {
+ bitset.set(0);
+ } else if ( "value22".equals(v) && !bitset.get(1) ) {
+ bitset.set(1);
+ } else {
+ fail( "Unexpected attribute value " + v );
+ }
+ }
+
+ // Encoded attribute
+ attributes = new AttributesImpl();
+ uri = new URI( "admin:///tenants/tenant/lucky?na%3Dme2=val%26ue1&na%3Dme2=val%3Due2" );
+ addAttributesFromUriQuery( uri, attributes, !REPLACE );
+ assertEquals("Attributes count", 1, attributes.getAttributeCount());
+ assertNotNull("attribute", attribute = attributes.getAttribute("na=me2"));
+ values = attribute.getValues();
+ assertEquals("Values count", 2, values.size());
+ bitset = new BitSet(2);
+ for ( String v : values ) {
+ if ( "val&ue1".equals(v) && !bitset.get(0) ) {
+ bitset.set(0);
+ } else if ( "val=ue2".equals(v) && !bitset.get(1) ) {
+ bitset.set(1);
+ } else {
+ fail( "Unexpected attribute value " + v );
+ }
+ }
+ }
+
+ @Test
+ public void testdecodeURI() throws Exception {
+ assertNull( "Expected null", decodeURI(null) );
+
+ assertEquals( "decoded",
+ "#($^&#&(*$C@#$*&^@#*&(|}|}{|}dfaj;",
+ decodeURI( "%23(%24%5E%26%23%26(*%24C%40%23%24*%26%5E%40%23*%26(%7C%7D%7C%7D%7B%7C%7Ddfaj%3B" ) );
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImplTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImplTest.java
new file mode 100644
index 0000000..f9a56ea
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/authorization/RoleMappingServiceImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.authorization;
+
+import java.net.URI;
+import javax.security.auth.Subject;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static junit.framework.Assert.*;
+
+import org.glassfish.security.services.api.authorization.AuthorizationService;
+import static org.glassfish.security.services.impl.authorization.RoleMappingServiceImpl.InitializationState.*;
+
+/**
+ * @see RoleMappingServiceImpl
+ */
+public class RoleMappingServiceImplTest {
+
+ // Use Authorization for creating the Az typed arguments on Role Service
+ private AuthorizationService authorizationService = new AuthorizationServiceImpl();
+ private RoleMappingServiceImpl impl;
+
+ @Before
+ public void setUp() throws Exception {
+ impl = new RoleMappingServiceImpl();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ impl = null;
+ }
+
+ @Test
+ public void testInitialize() throws Exception {
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+ try {
+ impl.initialize(null);
+ } catch ( RuntimeException e ) {
+ fail( "Expected service to allow no specified configuration" );
+ }
+
+ try {
+ impl.isUserInRole("test",
+ authorizationService.makeAzSubject(new Subject()),
+ authorizationService.makeAzResource(URI.create("test://test")),
+ "aRole");
+ fail( "Expected fail illegal state exception." );
+ } catch ( IllegalStateException e ) {
+ assertNotNull("Service fails at run-time", e);
+ }
+
+ // The service will fail internally to prevent method calls
+ assertSame( "FAILED_INIT", FAILED_INIT, impl.getInitializationState() );
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testIsUserRole() throws Exception {
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+ try {
+ impl.isUserInRole("test",
+ authorizationService.makeAzSubject(new Subject()),
+ authorizationService.makeAzResource(URI.create("test://test")),
+ "aRole");
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testIsUserRoleNoAzArgs() throws Exception {
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+ try {
+ impl.isUserInRole("test",
+ new Subject(),
+ URI.create("test://test"),
+ "aRole");
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull( "getReasonInitializationFailed", impl.getReasonInitializationFailed() );
+ }
+
+ @Test
+ public void testIsUserRoleNullArgs() throws Exception {
+ // Arguments checked before service state
+ try {
+ impl.isUserInRole("test",
+ null,
+ authorizationService.makeAzResource(URI.create("test://test")),
+ "aRole");
+ fail( "Expected fail illegal argument." );
+ } catch ( IllegalArgumentException e ) {
+ assertNotNull("Subject null test", e);
+ }
+ try {
+ impl.isUserInRole("test",
+ authorizationService.makeAzSubject(new Subject()),
+ null,
+ "aRole");
+ fail( "Expected fail illegal argument." );
+ } catch ( IllegalArgumentException e ) {
+ assertNotNull("Resource null test", e);
+ }
+ }
+
+ @Test
+ public void testIsUserRoleNoAzArgsNullArgs() throws Exception {
+ // Arguments checked before service state
+ try {
+ impl.isUserInRole("test",
+ null,
+ URI.create("test://test"),
+ "aRole");
+ fail( "Expected fail illegal argument." );
+ } catch ( IllegalArgumentException e ) {
+ assertNotNull("Subject null test", e);
+ }
+ try {
+ impl.isUserInRole("test",
+ new Subject(),
+ null,
+ "aRole");
+ fail( "Expected fail illegal argument." );
+ } catch ( IllegalArgumentException e ) {
+ assertNotNull("Subject null test", e);
+ }
+ }
+
+ @Test
+ public void testFindOrCreateDeploymentContext() throws Exception {
+ assertSame( "NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState() );
+ try {
+ impl.findOrCreateDeploymentContext("test");
+ fail( "Expected fail not initialized." );
+ } catch ( RuntimeException e ) {
+ }
+
+ assertSame("NOT_INITIALIZED", NOT_INITIALIZED, impl.getInitializationState());
+ assertNotNull("getReasonInitializationFailed", impl.getReasonInitializationFailed());
+ }
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributeTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributeTest.java
new file mode 100644
index 0000000..f3ba767
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributeTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.common;
+
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.glassfish.security.services.api.common.Attribute;
+
+
+public class AttributeTest {
+
+
+ @Test
+ public void testAttribute() {
+
+ String attName = "test";
+ Attribute att = new AttributeImpl(attName);
+ att.addValue("value1");
+ att.addValue("value2");
+
+ Set<String> vs = att.getValues();
+ Assert.assertEquals(2, att.getValueCount());
+ Assert.assertTrue(vs.contains("value1"));
+ Assert.assertTrue(vs.contains("value2"));
+ }
+
+ @Test
+ public void testAttributeNullValue() {
+
+ String attName = "testnull";
+ Attribute att = new AttributeImpl(attName);
+ att.addValue(null);
+
+ Set<String> vs = att.getValues();
+ Assert.assertTrue(vs.isEmpty());
+ }
+
+
+ @Test
+ public void testAttributeNullValue1() {
+
+ String attName = "testnull1";
+ Attribute att = new AttributeImpl(attName);
+ att.addValue(null);
+ att.addValue("value1");
+
+ Set<String> vs = att.getValues();
+ Assert.assertEquals(1, att.getValueCount());
+ Assert.assertTrue(vs.contains("value1"));
+ }
+
+ @Test
+ public void testAttributeEmptyValue() {
+
+ String attName = "testEmpty";
+ Attribute att = new AttributeImpl(attName);
+ att.addValue("");
+
+ Set<String> vs = att.getValues();
+ Assert.assertTrue(vs.isEmpty());
+ }
+
+
+}
diff --git a/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributesTest.java b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributesTest.java
new file mode 100644
index 0000000..3cec850
--- /dev/null
+++ b/nucleus/security/services/src/test/java/org/glassfish/security/services/impl/common/AttributesTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.security.services.impl.common;
+
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+import org.glassfish.security.services.api.common.Attributes;
+
+
+
+public class AttributesTest {
+
+ @Test
+ public void testAttributes() {
+
+ String attName = "test";
+ Attributes att = new AttributesImpl();
+ att.addAttribute(attName, "value1", false);
+ att.addAttribute(attName, "value2", false);
+
+ Set<String> vs = att.getAttributeValues(attName);
+ Assert.assertEquals(2, vs.size());
+ Assert.assertTrue(vs.contains("value1"));
+ Assert.assertTrue(vs.contains("value2"));
+ }
+
+
+ @Test
+ public void testAttributesReplace() {
+
+ String attName = "test";
+ Attributes att = new AttributesImpl();
+ att.addAttribute(attName, "value1", false);
+ att.addAttribute(attName, "value2", true);
+
+ Set<String> vs = att.getAttributeValues(attName);
+ Assert.assertEquals(1, vs.size());
+ Assert.assertFalse(vs.contains("value1"));
+ Assert.assertTrue(vs.contains("value2"));
+ }
+
+ @Test
+ public void testAttributesNull() {
+
+ String attName = "test";
+ Attributes att = new AttributesImpl();
+ att.addAttribute(attName, (String)null, false);
+
+ Set<String> vs = att.getAttributeValues(attName);
+ Assert.assertEquals(0, vs.size());
+ }
+
+ @Test
+ public void testAttributesEmpty() {
+
+ String attName = "test";
+ Attributes att = new AttributesImpl();
+ att.addAttribute(attName, "", false);
+
+ Set<String> vs = att.getAttributeValues(attName);
+ Assert.assertEquals(0, vs.size());
+ }
+
+}
diff --git a/nucleus/security/ssl-impl/osgi.bundle b/nucleus/security/ssl-impl/osgi.bundle
new file mode 100644
index 0000000..87aad9d
--- /dev/null
+++ b/nucleus/security/ssl-impl/osgi.bundle
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+-exportcontents: \
+ com.sun.enterprise.security.ssl.manager; \
+ com.sun.enterprise.server.pluggable; version=${project.osgi.version}
+
+DynamicImport-Package: \
+ com.sun.enterprise.security.store
+
diff --git a/nucleus/security/ssl-impl/pom.xml b/nucleus/security/ssl-impl/pom.xml
new file mode 100644
index 0000000..21cbd09
--- /dev/null
+++ b/nucleus/security/ssl-impl/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>nucleus-security</artifactId>
+ <groupId>org.glassfish.main.security</groupId>
+ <version>5.0.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>ssl-impl</artifactId>
+ <packaging>glassfish-jar</packaging>
+
+ <version>5.0.1-SNAPSHOT</version>
+ <name>GlassFish SSL Implementation Module</name>
+ <developers>
+ <developer>
+ <id>nasradu8</id>
+ <name>Sudarsan Sridhar</name>
+ <organization>Oracle, Inc.</organization>
+ <roles>
+ <role>developer</role>
+ </roles>
+ </developer>
+ </developers>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>internal-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>common-util</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency> <!-- for FindBugs -->
+ <groupId>org.glassfish.main.common</groupId>
+ <artifactId>simple-glassfish-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.hk2</groupId>
+ <artifactId>hk2-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.annotations</groupId>
+ <artifactId>logging-annotation-processor</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java
new file mode 100644
index 0000000..184fa9f
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl.impl;
+
+import com.sun.enterprise.security.store.IdentityManagement;
+import com.sun.enterprise.security.store.PasswordAdapter;
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.glassfish.security.common.MasterPassword;
+import org.jvnet.hk2.annotations.Optional;
+import org.jvnet.hk2.annotations.Service;
+
+/**
+ * A contract to pass the Glassfish master password between the admin module and
+ * the security module.
+ *
+ * @author Sudarsan Sridhar
+ */
+@Service(name="Security SSL Password Provider Service")
+@Singleton
+public class MasterPasswordImpl implements MasterPassword {
+
+ @Inject @Optional IdentityManagement idm;
+
+ @Override
+ public PasswordAdapter getMasterPasswordAdapter() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException {
+ char pw[] = idm == null ? null : idm.getMasterPassword();
+ return new PasswordAdapter(pw);
+ }
+
+ public char[] getMasterPassword() {
+ return idm == null ? null : idm.getMasterPassword();
+ }
+}
diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java
new file mode 100644
index 0000000..8044706
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl.impl;
+
+import com.sun.enterprise.security.ssl.manager.UnifiedX509KeyManager;
+import com.sun.enterprise.security.ssl.manager.UnifiedX509TrustManager;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.security.KeyStore;
+import java.security.Provider;
+
+//V3:Commented import com.sun.enterprise.config.ConfigContext;
+import com.sun.enterprise.server.pluggable.SecuritySupport;
+import java.io.IOException;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.Key;
+import java.security.Permission;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.PropertyPermission;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import org.glassfish.api.admin.ProcessEnvironment;
+import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.internal.embedded.Server;
+import org.glassfish.internal.api.Globals;
+import org.glassfish.logging.annotation.LogMessageInfo;
+import org.glassfish.logging.annotation.LogMessagesResourceBundle;
+import org.glassfish.logging.annotation.LoggerInfo;
+
+import javax.inject.Inject;
+import org.jvnet.hk2.annotations.Service;
+
+import javax.inject.Singleton;
+
+/**
+ * This implements SecuritySupport used in PluggableFeatureFactory.
+ * @author Shing Wai Chan
+ */
+// TODO: when we have two SecuritySupport implementations,
+// we create Habitat we'll select which SecuritySupport implementation to use.
+@Service
+@Singleton
+public class SecuritySupportImpl extends SecuritySupport {
+ private static final String DEFAULT_KEYSTORE_PASS = "changeit";
+ private static final String DEFAULT_TRUSTSTORE_PASS = "changeit";
+
+ @LogMessagesResourceBundle
+ public static final String SHARED_LOGMESSAGE_RESOURCE = "com.sun.enterprise.security.ssl.LogMessages";
+
+ @LoggerInfo(subsystem = "SECURITY - SSL", description = "Security - SSL", publish = true)
+ public static final String SEC_SSL_LOGGER = "javax.enterprise.system.security.ssl";
+
+ protected static final Logger _logger =
+ Logger.getLogger(SEC_SSL_LOGGER, SHARED_LOGMESSAGE_RESOURCE);
+
+ @LogMessageInfo(
+ message = "The SSL certificate has expired: {0}",
+ level = "SEVERE",
+ cause = "Certificate expired.",
+ action = "Check the expiration date of the certicate.")
+ private static final String SSL_CERT_EXPIRED = "NCLS-SECURITY-05054";
+
+ private static boolean initialized = false;
+ protected static final List<KeyStore> keyStores = new ArrayList<KeyStore>();
+ protected static final List<KeyStore> trustStores = new ArrayList<KeyStore>();
+ protected static final List<char[]> keyStorePasswords = new ArrayList<char[]>();
+ protected static final List<String> tokenNames = new ArrayList<String>();
+ private MasterPasswordImpl masterPasswordHelper = null;
+ private static boolean instantiated = false;
+ private Date initDate = new Date();
+
+ @Inject
+ private ServiceLocator habitat;
+ @Inject
+ private ProcessEnvironment penv;
+
+ public SecuritySupportImpl() {
+ this(true);
+ }
+
+ protected SecuritySupportImpl(boolean init) {
+ if (init) {
+ initJKS();
+ }
+ }
+
+ private void initJKS() {
+ String keyStoreFileName = null;
+ String trustStoreFileName = null;
+
+ keyStoreFileName = System.getProperty(keyStoreProp);
+ trustStoreFileName = System.getProperty(trustStoreProp);
+
+ char[] keyStorePass = null;
+ char[] trustStorePass = null;
+ if (!isInstantiated()) {
+ if (habitat == null) {
+ habitat = Globals.getDefaultHabitat();
+ }
+ if (masterPasswordHelper == null && habitat != null) {
+ masterPasswordHelper = habitat.getService(MasterPasswordImpl.class);
+ }
+ if (masterPasswordHelper != null) {
+ keyStorePass = masterPasswordHelper.getMasterPassword();
+ trustStorePass = keyStorePass;
+ }
+ }
+ if (penv == null && habitat != null) {
+ penv = habitat.getService(ProcessEnvironment.class);
+ }
+ /*
+ * If we don't have a keystore password yet check the properties.
+ * Always do so for the app client case whether the passwords have been
+ * found from master password helper or not.
+ */
+ if (keyStorePass == null || isACC()) {
+ final String keyStorePassOverride = System.getProperty(KEYSTORE_PASS_PROP, DEFAULT_KEYSTORE_PASS);
+ if (keyStorePassOverride != null) {
+ keyStorePass = keyStorePassOverride.toCharArray();
+ }
+ final String trustStorePassOverride = System.getProperty(TRUSTSTORE_PASS_PROP, DEFAULT_TRUSTSTORE_PASS);
+ if (trustStorePassOverride != null){
+ trustStorePass = trustStorePassOverride.toCharArray();
+ }
+ }
+
+ if (!initialized) {
+ loadStores(
+ null,
+ null,
+ keyStoreFileName,
+ keyStorePass,
+ System.getProperty(KEYSTORE_TYPE_PROP, KeyStore.getDefaultType()),
+ trustStoreFileName,
+ trustStorePass,
+ System.getProperty(TRUSTSTORE_TYPE_PROP, KeyStore.getDefaultType()));
+ Arrays.fill(keyStorePass, ' ');
+ Arrays.fill(trustStorePass, ' ');
+ initialized = true;
+ }
+ }
+
+ private boolean isEmbeddedServer() {
+ List<String> servers = Server.getServerNames();
+ if (!servers.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ private static synchronized boolean isInstantiated() {
+ if (!instantiated) {
+ instantiated = true;
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method will load keystore and truststore and add into
+ * corresponding list.
+ * @param tokenName
+ * @param provider
+ * @param keyStorePass
+ * @param keyStoreFile
+ * @param keyStoreType
+ * @param trustStorePass
+ * @param trustStoreFile
+ * @param trustStoreType
+ */
+ /*protected synchronized static void loadStores(String tokenName,
+ String storeType, Provider provider,
+ String keyStoreFile, String keyStorePass,
+ String trustStoreFile, String trustStorePass) {*/
+ protected synchronized static void loadStores(
+ String tokenName,
+ Provider provider,
+ String keyStoreFile,
+ char[] keyStorePass,
+ String keyStoreType,
+ String trustStoreFile,
+ char[] trustStorePass,
+ String trustStoreType) {
+
+ try {
+ KeyStore keyStore = loadKS(keyStoreType, provider, keyStoreFile,
+ keyStorePass);
+ KeyStore trustStore = loadKS(trustStoreType, provider, trustStoreFile,
+ trustStorePass);
+ keyStores.add(keyStore);
+ trustStores.add(trustStore);
+ keyStorePasswords.add(Arrays.copyOf(keyStorePass, keyStorePass.length));
+ tokenNames.add(tokenName);
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ /**
+ * This method load keystore with given keystore file and
+ * keystore password for a given keystore type and provider.
+ * It always return a non-null keystore.
+ * @param keyStoreType
+ * @param provider
+ * @param keyStoreFile
+ * @param keyStorePass
+ * @retun keystore loaded
+ */
+ private static KeyStore loadKS(String keyStoreType, Provider provider,
+ String keyStoreFile, char[] keyStorePass)
+ throws Exception {
+ KeyStore ks = null;
+ if (provider != null) {
+ ks = KeyStore.getInstance(keyStoreType, provider);
+ } else {
+ ks = KeyStore.getInstance(keyStoreType);
+ }
+ char[] passphrase = keyStorePass;
+
+ FileInputStream istream = null;
+ BufferedInputStream bstream = null;
+ try {
+ if (keyStoreFile != null) {
+ if (_logger.isLoggable(Level.FINE)) {
+ _logger.log(Level.FINE, "Loading keystoreFile = {0}, keystorePass = {1}",
+ new Object[]{keyStoreFile, keyStorePass});
+ }
+ istream = new FileInputStream(keyStoreFile);
+ bstream = new BufferedInputStream(istream);
+ }
+
+ ks.load(bstream, passphrase);
+ } finally {
+ if (bstream != null) {
+ bstream.close();
+ }
+ if (istream != null) {
+ istream.close();
+ }
+ }
+ return ks;
+ }
+
+ // --- implements SecuritySupport ---
+ /**
+ * This method returns an array of keystores containing keys and
+ * certificates.
+ */
+ public KeyStore[] getKeyStores() {
+ return keyStores.toArray(new KeyStore[keyStores.size()]);
+ }
+
+ public KeyStore loadNullStore(String type, int index) throws KeyStoreException,
+ IOException, NoSuchAlgorithmException, CertificateException {
+ KeyStore ret = KeyStore.getInstance(type);
+ ret.load(null, keyStorePasswords.get(index));
+ return ret;
+ }
+
+ public KeyManager[] getKeyManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
+ KeyStore[] kstores = getKeyStores();
+ ArrayList<KeyManager> keyManagers = new ArrayList<KeyManager>();
+ for (int i = 0; i < kstores.length; i++) {
+ checkCertificateDates(kstores[i]);
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+ (algorithm != null) ? algorithm : KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(kstores[i], keyStorePasswords.get(i));
+ KeyManager[] kmgrs = kmf.getKeyManagers();
+ if (kmgrs != null) {
+ keyManagers.addAll(Arrays.asList(kmgrs));
+ }
+ }
+
+ KeyManager keyManager = new UnifiedX509KeyManager(
+ keyManagers.toArray(new X509KeyManager[keyManagers.size()]),
+ getTokenNames());
+ return new KeyManager[]{keyManager};
+ }
+
+ public TrustManager[] getTrustManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException {
+ KeyStore[] tstores = getTrustStores();
+ ArrayList<TrustManager> trustManagers = new ArrayList<TrustManager>();
+ for (KeyStore tstore : tstores) {
+ checkCertificateDates(tstore);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+ (algorithm != null) ? algorithm : TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(tstore);
+ TrustManager[] tmgrs = tmf.getTrustManagers();
+ if (tmgrs != null) {
+ trustManagers.addAll(Arrays.asList(tmgrs));
+ }
+ }
+ TrustManager trustManager;
+ if (trustManagers.size() == 1) {
+ trustManager = trustManagers.get(0);
+ } else {
+ trustManager = new UnifiedX509TrustManager(trustManagers.toArray(new X509TrustManager[trustManagers.size()]));
+ }
+ return new TrustManager[]{trustManager};
+ }
+ /*
+ * Check X509 certificates in a store for expiration.
+ */
+
+ private void checkCertificateDates(KeyStore store)
+ throws KeyStoreException {
+
+ Enumeration<String> aliases = store.aliases();
+ while (aliases.hasMoreElements()) {
+ Certificate cert = store.getCertificate(aliases.nextElement());
+ if (cert instanceof X509Certificate) {
+ if (((X509Certificate) cert).getNotAfter().before(initDate)) {
+ _logger.log(Level.SEVERE, SSL_CERT_EXPIRED, cert);
+ }
+ }
+ }
+ }
+
+ /**
+ * This method returns an array of truststores containing certificates.
+ */
+ public KeyStore[] getTrustStores() {
+ return trustStores.toArray(new KeyStore[trustStores.size()]);
+ }
+
+ public boolean verifyMasterPassword(final char[] masterPass) {
+ return Arrays.equals(masterPass, keyStorePasswords.get(0));
+ }
+
+ /**
+ * This method returns an array of token names in order corresponding to
+ * array of keystores.
+ */
+ public String[] getTokenNames() {
+ return tokenNames.toArray(new String[tokenNames.size()]);
+ }
+
+ /**
+ * @param token
+ * @return a keystore
+ */
+ public KeyStore getKeyStore(String token) {
+ int idx = getTokenIndex(token);
+ if (idx < 0) {
+ return null;
+ }
+ return keyStores.get(idx);
+ }
+
+ /**
+ * @param token
+ * @return a truststore
+ */
+ public KeyStore getTrustStore(String token) {
+ int idx = getTokenIndex(token);
+ if (idx < 0) {
+ return null;
+ }
+ return trustStores.get(idx);
+ }
+
+ /**
+ * @return returned index
+ */
+ private int getTokenIndex(String token) {
+ int idx = -1;
+ if (token != null) {
+ idx = tokenNames.indexOf(token);
+ if (idx < 0 && _logger.isLoggable(Level.FINEST)) {
+ _logger.log(Level.FINEST, "token {0} is not found", token);
+ }
+ }
+ return idx;
+ }
+
+ public void synchronizeKeyFile(Object configContext, String fileRealmName) throws Exception {
+ //throw new UnsupportedOperationException("Not supported yet in V3.");
+ }
+
+ public void checkPermission(String key) {
+ try {
+ // Checking a random permission to check if it is server.
+ if(isEmbeddedServer() || habitat == null
+ || isACC() || isNotServerORACC()){
+ return;
+ }
+ Permission perm = new RuntimePermission("SSLPassword");
+ AccessController.checkPermission(perm);
+ } catch (AccessControlException e) {
+ String message = e.getMessage();
+ Permission perm = new PropertyPermission(key, "read");
+ if (message != null) {
+ message = message.replace(e.getPermission().toString(), perm.toString());
+ }
+ throw new AccessControlException(message, perm);
+ }
+ }
+
+ public boolean isACC() {
+ return (penv == null ? false : penv.getProcessType().equals(ProcessType.ACC));
+ }
+
+ public boolean isNotServerORACC() {
+ return penv.getProcessType().equals(ProcessType.Other);
+ }
+
+ public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
+ checkPermission(KEYSTORE_PASS_PROP);
+ Key key = keyStores.get(keystoreIndex).getKey(alias, keyStorePasswords.get(keystoreIndex));
+ if (key instanceof PrivateKey) {
+ return (PrivateKey) key;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509KeyManager.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509KeyManager.java
new file mode 100644
index 0000000..67546f3
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509KeyManager.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl.manager;
+
+import java.net.Socket;
+import java.util.ArrayList;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509KeyManager;
+
+/**
+ * This class combines an array of X509KeyManagers into one.
+ * @author Shing Wai Chan
+ **/
+public class UnifiedX509KeyManager implements X509KeyManager /* extends X509ExtendedKeyManager*/ {
+ private X509KeyManager[] mgrs = null;
+ private String[] tokenNames = null;
+
+ /**
+ * @param mgrs
+ * @param tokenNames Array of tokenNames with order corresponding to mgrs
+ */
+ public UnifiedX509KeyManager(X509KeyManager[] mgrs, String[] tokenNames) {
+ if (mgrs == null || tokenNames == null) {
+ throw new IllegalArgumentException("Null array of X509KeyManagers or tokenNames");
+ }
+ if (mgrs.length != tokenNames.length) {
+ throw new IllegalArgumentException("Size of X509KeyManagers array and tokenNames array do not match.");
+ }
+ this.mgrs = mgrs;
+ this.tokenNames = tokenNames;
+ }
+
+ // ---------- implements X509KeyManager ----------
+ public String chooseClientAlias(String[] keyType, Principal[] issuers,
+ Socket socket) {
+ String alias = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ alias = mgrs[i].chooseClientAlias(keyType, issuers, socket);
+ if (alias != null) {
+ break;
+ }
+ }
+ return alias;
+ }
+
+ public String chooseServerAlias(String keyType, Principal[] issuers,
+ Socket socket) {
+ String alias = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ alias = mgrs[i].chooseServerAlias(keyType, issuers, socket);
+ if (alias != null) {
+ break;
+ }
+ }
+ return alias;
+ }
+
+ public X509Certificate[] getCertificateChain(String alias) {
+ X509Certificate[] chain = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ chain = mgrs[i].getCertificateChain(alias);
+ if (chain != null) {
+ break;
+ }
+ }
+ return chain;
+ }
+
+ public String[] getClientAliases(String keyType, Principal[] issuers) {
+ ArrayList clientAliases = new ArrayList();
+ for (int i = 0; i < mgrs.length; i++) {
+ String[] clAliases = mgrs[i].getClientAliases(keyType, issuers);
+ if (clAliases != null && clAliases.length > 0) {
+ for (int j = 0; j < clAliases.length; j++) {
+ clientAliases.add(clAliases[j]);
+ }
+ }
+ }
+
+ return (clientAliases.size() == 0) ? null :
+ (String[])clientAliases.toArray(new String[clientAliases.size()]);
+ }
+
+ public PrivateKey getPrivateKey(String alias) {
+ PrivateKey privKey = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ privKey = mgrs[i].getPrivateKey(alias);
+ if (privKey != null) {
+ break;
+ }
+ }
+ return privKey;
+ }
+
+ public String[] getServerAliases(String keyType, Principal[] issuers) {
+ ArrayList serverAliases = new ArrayList();
+ for (int i = 0; i < mgrs.length; i++) {
+ String[] serAliases = mgrs[i].getServerAliases(keyType, issuers);
+ if (serAliases != null && serAliases.length > 0) {
+ for (int j = 0; j < serAliases.length; j++) {
+ serverAliases.add(serAliases[j]);
+ }
+ }
+ }
+
+ return (serverAliases.size() == 0) ? null :
+ (String[])serverAliases.toArray(new String[serverAliases.size()]);
+ }
+
+ // ---------- end of implements X509KeyManager ----------
+
+ public X509KeyManager[] getX509KeyManagers() {
+ X509KeyManager[] kmgrs = new X509KeyManager[mgrs.length];
+ System.arraycopy(mgrs, 0, kmgrs, 0, mgrs.length);
+ return kmgrs;
+ }
+
+ public String[] getTokenNames() {
+ String[] tokens = new String[tokenNames.length];
+ System.arraycopy(tokenNames, 0, tokens, 0, tokenNames.length);
+ return tokens;
+ }
+
+
+ public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
+ return chooseClientAlias(keyType, issuers, null);
+ }
+
+ public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
+ return chooseServerAlias(keyType, issuers,null);
+ }
+}
diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509TrustManager.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509TrustManager.java
new file mode 100644
index 0000000..d81c63d
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/manager/UnifiedX509TrustManager.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.security.ssl.manager;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * This class combines an array of X509TrustManagers into one.
+ * @author Shing Wai Chan
+ **/
+public class UnifiedX509TrustManager implements X509TrustManager {
+ private X509TrustManager[] mgrs = null;
+ private X509Certificate[] issuers = {};
+
+ public UnifiedX509TrustManager(X509TrustManager[] mgrs) {
+ if (mgrs == null) {
+ throw new IllegalArgumentException("Null array of X509TrustManagers");
+ }
+ this.mgrs = mgrs;
+
+ HashSet tset = new HashSet(); //for uniqueness
+ for (int i = 0; i < mgrs.length; i++) {
+ X509Certificate[] tcerts = mgrs[i].getAcceptedIssuers();
+ if (tcerts != null && tcerts.length > 0) {
+ for (int j = 0; j < tcerts.length; j++) {
+ tset.add(tcerts[j]);
+ }
+ }
+ }
+ issuers = new X509Certificate[tset.size()];
+ Iterator iter = tset.iterator();
+ for (int i = 0; iter.hasNext(); i++) {
+ issuers[i] = (X509Certificate)iter.next();
+ }
+ }
+
+ // ---------- implements X509TrustManager -----------
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ CertificateException cex = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ try {
+ cex = null; //reset exception status
+ mgrs[i].checkClientTrusted(chain, authType);
+ break;
+ } catch(CertificateException ex) {
+ cex = ex;
+ }
+ }
+ if (cex != null) {
+ throw cex;
+ }
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ CertificateException cex = null;
+ for (int i = 0; i < mgrs.length; i++) {
+ try {
+ cex = null; //reset exception status
+ mgrs[i].checkServerTrusted(chain, authType);
+ break;
+ } catch(CertificateException ex) {
+ cex = ex;
+ }
+ }
+ if (cex != null) {
+ throw cex;
+ }
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return issuers;
+ }
+}
diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java
new file mode 100644
index 0000000..0ee72ea
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.enterprise.server.pluggable;
+
+import com.sun.enterprise.security.ssl.impl.SecuritySupportImpl;
+import java.io.IOException;
+import java.security.KeyStore;
+//V3:Commented import com.sun.enterprise.config.ConfigContext;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.TrustManager;
+import org.jvnet.hk2.annotations.Contract;
+
+/**
+ * SecuritySupport is part of PluggableFeature that provides access to
+ * internal services managed by application server.
+ * @author Shing Wai Chan
+ */
+@Contract
+public abstract class SecuritySupport {
+
+ public static final String KEYSTORE_PASS_PROP = "javax.net.ssl.keyStorePassword";
+ public static final String TRUSTSTORE_PASS_PROP = "javax.net.ssl.trustStorePassword";
+ public static final String KEYSTORE_TYPE_PROP = "javax.net.ssl.keyStoreType";
+ public static final String TRUSTSTORE_TYPE_PROP = "javax.net.ssl.trustStoreType";
+ public static final String keyStoreProp = "javax.net.ssl.keyStore";
+ public static final String trustStoreProp = "javax.net.ssl.trustStore";
+
+ private static volatile SecuritySupport defaultInstance = null;
+
+ public static SecuritySupport getDefaultInstance() {
+ if (defaultInstance == null) {
+ defaultInstance = new SecuritySupportImpl();
+ }
+ return defaultInstance;
+ }
+
+
+ /**
+ * This method returns an array of keystores containing keys and
+ * certificates.
+ */
+ abstract public KeyStore[] getKeyStores();
+
+ /**
+ * This method returns an array of truststores containing certificates.
+ */
+ abstract public KeyStore[] getTrustStores();
+
+ /**
+ * @param token
+ * @return a keystore. If token is null, return the the first keystore.
+ */
+ abstract public KeyStore getKeyStore(String token);
+
+ /**
+ * @param token
+ * @return a truststore. If token is null, return the first truststore.
+ */
+ abstract public KeyStore getTrustStore(String token);
+
+ /**
+ * @param type
+ * @param index
+ * @return load a null keystore of given type.
+ */
+ abstract public KeyStore loadNullStore(String type, int index) throws KeyStoreException,
+ IOException, NoSuchAlgorithmException, CertificateException;
+
+ /**
+ * @param masterPass
+ * @return result whether the given master password is correct.
+ */
+ abstract public boolean verifyMasterPassword(final char[] masterPass);
+
+ /**
+ * @param algorithm
+ * @return KeyManagers for the specified algorithm.
+ * @throws IOException
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws UnrecoverableKeyException
+ */
+ abstract public KeyManager[] getKeyManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException;
+
+ /**
+ * @param algorithm
+ * @return TrustManagers for the specified algorithm.
+ * @throws IOException
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ */
+ abstract public TrustManager[] getTrustManagers(String algorithm) throws IOException,
+ KeyStoreException, NoSuchAlgorithmException;
+
+ /**
+ * Gets the PrivateKey for specified alias from the corresponding keystore
+ * indicated by the index.
+ *
+ * @param alias Alias for which the PrivateKey is desired.
+ * @param keystoreIndex Index of the keystore.
+ * @return
+ * @throws KeyStoreException
+ * @throws NoSuchAlgorithmException
+ * @throws UnrecoverableKeyException
+ */
+ abstract public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex)
+ throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException;
+
+ /**
+ * This method returns an array of token names in order corresponding to
+ * array of keystores.
+ */
+ abstract public String[] getTokenNames();
+
+ /**
+ * This method synchronize key file for given realm.
+ * @param config the ConfigContextx
+ * @param fileRealmName
+ * @exception if fail to synchronize, a known exception is
+ * com.sun.enterprise.ee.synchronization.SynchronizationException
+ */
+ /** TODO:V3:Cluster ConfigContext is no longer present so find out what this needs to be */
+ //public void synchronizeKeyFile(ConfigContext config, String fileRealmName)
+ abstract public void synchronizeKeyFile(Object configContext, String fileRealmName)
+ throws Exception;
+
+ /**
+ * Check permission for the given key.
+ * @param key
+ */
+ abstract public void checkPermission(String key);
+
+}
diff --git a/nucleus/security/ssl-impl/src/main/resources/com/sun/logging/enterprise/system/ssl/security/LogStrings.properties b/nucleus/security/ssl-impl/src/main/resources/com/sun/logging/enterprise/system/ssl/security/LogStrings.properties
new file mode 100644
index 0000000..bfa20f7
--- /dev/null
+++ b/nucleus/security/ssl-impl/src/main/resources/com/sun/logging/enterprise/system/ssl/security/LogStrings.properties
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+#
+
+java_security.expired_certificate=SEC5054: Certificate has expired: {0}
+
+SEC5054.diag.cause.1=Certificate expired
+SEC5054.diag.check.1=Please check the validity date of the certificate