extends Function {
+ default T apply(P p) {
+ return run(p);
+ }
+
+ /**
+ * Perform the action.
+ *
+ * @param parameter the passed-in parameter
+ * @return the action result
+ */
+ T run(P parameter);
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/ParametricPrivilegedExceptionAction.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/ParametricPrivilegedExceptionAction.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/ParametricPrivilegedExceptionAction.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import org.wildfly.common.function.ExceptionFunction;
+
+/**
+ * A privileged action which accepts a parameter and can throw an exception.
+ *
+ * @param the action result type
+ * @param the action parameter type
+ *
+ * @author David M. Lloyd
+ */
+@FunctionalInterface
+public interface ParametricPrivilegedExceptionAction extends ExceptionFunction {
+ default T apply(P p) throws Exception {
+ return run(p);
+ }
+
+ /**
+ * Perform the action.
+ *
+ * @param parameter the passed-in parameter
+ * @return the action result
+ * @throws Exception if the action fails
+ */
+ T run(P parameter) throws Exception;
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/SecurityFactory.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/SecurityFactory.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/SecurityFactory.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * A factory for preconfigured security objects.
+ *
+ * @author David M. Lloyd
+ */
+@FunctionalInterface
+public interface SecurityFactory {
+
+ /**
+ * Create an instance.
+ *
+ * @return the new instance
+ * @throws GeneralSecurityException if instantiation fails for some reason
+ */
+ T create() throws GeneralSecurityException;
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/Version.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/Version.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/Version.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2013 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+/**
+ * The version of this JAR.
+ *
+ * @author David M. Lloyd
+ */
+public final class Version {
+
+ private Version() {
+ }
+
+ private static final String VERSION;
+ private static final String JAR_NAME;
+
+ static {
+ Properties versionProps = new Properties();
+ String versionString = "(unknown)";
+ String jarName = "(unknown)";
+ try (final InputStream stream = Version.class.getResourceAsStream("Version.properties")) {
+ try (final InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
+ versionProps.load(reader);
+ versionString = versionProps.getProperty("version", versionString);
+ jarName = versionProps.getProperty("jarName", jarName);
+ }
+ } catch (IOException ignored) {
+ }
+ VERSION = versionString;
+ JAR_NAME = jarName;
+ try {
+ ElytronMessages.log.logVersion(versionString);
+ } catch (Throwable ignored) {}
+ }
+
+ /**
+ * Get the version.
+ *
+ * @return the version
+ */
+ public static String getVersion() {
+ return VERSION;
+ }
+
+ /**
+ * Get the JAR name.
+ *
+ * @return the JAR name
+ */
+ public static String getJarName() {
+ return JAR_NAME;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/Version.properties
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/Version.properties (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/Version.properties (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,2 @@
+version=${project.version}
+jarName=${project.artifactId}
Index: 3rdParty_sources/elytron/org/wildfly/security/VersionedProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/VersionedProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/VersionedProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+/**
+ * A security provider which uses a string version, forward compatible with Java 9.
+ */
+public abstract class VersionedProvider extends Provider {
+ private static final long serialVersionUID = 6973461237113228162L;
+
+ /**
+ * Constructs a provider with the specified name, version number,
+ * and information.
+ *
+ * @param name the provider name
+ * @param version the provider version number string
+ * @param info a description of the provider and its services
+ */
+ protected VersionedProvider(final String name, final String version, final String info) {
+ super(name, Double.parseDouble(version), info);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronBaseProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronBaseProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronBaseProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,227 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import static org.wildfly.security.ElytronMessages.log;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Provider.Service;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+/**
+ * The base {@link Provider} implementation for security services made available by Elytron.
+ *
+ * @author Darran Lofthouse
+ * @author David M. Lloyd
+ */
+public abstract class WildFlyElytronBaseProvider extends VersionedProvider {
+
+ protected static final String HTTP_SERVER_FACTORY_TYPE = "HttpServerAuthenticationMechanismFactory";
+ protected static final String SASL_CLIENT_FACTORY_TYPE = "SaslClientFactory";
+ protected static final String SASL_SERVER_FACTORY_TYPE = "SaslServerFactory";
+ protected static final String PASSWORD_FACTORY_TYPE = "PasswordFactory";
+ protected static final String ALG_PARAMS_TYPE = "AlgorithmParameters";
+ protected static final List emptyList = Collections.emptyList();
+ protected static final Map emptyMap = Collections.emptyMap();
+
+ private static final Collection MASKED_ALGORITHMS = Collections.unmodifiableCollection(Arrays.asList(
+ "masked-MD5-DES", "masked-MD5-DES-CBC-PKCS5", "masked-MD5-3DES", "masked-MD5-3DES-CBC-PKCS5", "masked-SHA1-DES-EDE",
+ "masked-SHA1-DES-EDE-CBC-PKCS5", "masked-SHA1-RC2-40", "masked-SHA1-RC2-40-CBC-PKCS5", "masked-SHA1-RC2-128",
+ "masked-SHA1-RC2-128-CBC-PKCS5", "masked-SHA1-RC4-40", "masked-SHA1-RC4-40-ECB", "masked-SHA1-RC4-128",
+ "masked-SHA1-RC4-128-ECB", "masked-HMAC-SHA1-AES-128", "masked-HMAC-SHA224-AES-128", "masked-HMAC-SHA256-AES-128",
+ "masked-HMAC-SHA384-AES-128", "masked-HMAC-SHA512-AES-128", "masked-HMAC-SHA1-AES-256",
+ "masked-HMAC-SHA224-AES-256", "masked-HMAC-SHA256-AES-256", "masked-HMAC-SHA384-AES-256",
+ "masked-HMAC-SHA512-AES-256"));
+
+ protected WildFlyElytronBaseProvider(final String name, final String version, final String info) {
+ super(name, version, info);
+ }
+
+ protected void putPasswordImplementations() {
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "clear", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "sun-crypt-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "sun-crypt-md5-bare-salt", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-md2", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-512-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-des", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "bsd-crypt-des", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "bcrypt", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putMakedPasswordImplementations(this::putService, this);
+ }
+
+ static void putMakedPasswordImplementations(Consumer consumer, Provider provider) {
+ for (String algorithm : MASKED_ALGORITHMS) {
+ consumer.accept(new Service(provider, PASSWORD_FACTORY_TYPE, algorithm, "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ }
+ }
+
+ protected void putAlgorithmParametersImplementations() {
+ putService(new Service(this, ALG_PARAMS_TYPE, "RSA", "org.wildfly.security.key.RSAParameterSpiImpl", emptyList, emptyMap));
+
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "sun-crypt-md5", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "sun-crypt-md5-bare-salt", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-sha-256", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-sha-512", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-md5", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-256", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-384", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-512", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-512-256", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-1", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-256", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-384", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-512", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-1", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-256", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-384", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-512", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-des", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "bsd-crypt-des", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "bcrypt", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-1", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-256", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-384", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-512", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-md5", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha1", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha256", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha384", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha512", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putMakedAlgorithmParametersImplementations(this::putService, this);
+ }
+
+ static void putMakedAlgorithmParametersImplementations(Consumer consumer, Provider provider) {
+ for (String algorithm : MASKED_ALGORITHMS) {
+ consumer.accept(new Service(provider, ALG_PARAMS_TYPE, algorithm, "org.wildfly.security.password.impl.MaskedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ }
+ }
+
+ protected class ProviderService extends Service {
+
+ private final boolean withProvider;
+ private final boolean reUsable;
+ private volatile Reference> implementationClassRef;
+ private volatile Reference instance;
+
+ public ProviderService(Provider provider, String type, String algorithm, String className, List aliases, Map attributes) {
+ this(provider, type, algorithm, className, aliases, attributes, true, false);
+ }
+
+ public ProviderService(Provider provider, String type, String algorithm, String className, List aliases, Map attributes, boolean withProvider, boolean reUsable) {
+ super(provider, type, algorithm, className, aliases, attributes);
+ this.withProvider = withProvider;
+ this.reUsable = reUsable;
+ }
+
+ @Override
+ public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException {
+ if (reUsable) {
+ Reference instance = this.instance;
+ Object response;
+ if (instance == null || (response = instance.get()) == null) {
+ synchronized(this) {
+ instance = this.instance;
+ if (instance == null || (response = instance.get()) == null) {
+ response = withProvider ? newInstance() : super.newInstance(constructorParameter);
+ this.instance = new SoftReference(response);
+ }
+ }
+ }
+
+ return response;
+ }
+
+ return withProvider ? newInstance() : super.newInstance(constructorParameter);
+ }
+
+ private Object newInstance() throws NoSuchAlgorithmException {
+ Class> implementationClass = getImplementationClass();
+
+ try {
+ Constructor> constructor = implementationClass.getConstructor(Provider.class);
+ return constructor.newInstance(WildFlyElytronBaseProvider.this);
+ } catch (Exception e) {
+ throw log.noSuchAlgorithmCreateService(getType(), getAlgorithm(), e);
+ }
+ }
+
+ private Class> getImplementationClass() throws NoSuchAlgorithmException {
+ Reference> implementationClassRef = this.implementationClassRef;
+ Class> implementationClass = implementationClassRef != null ? implementationClassRef.get() : null;
+ if (implementationClass == null) {
+ ClassLoader classLoader = WildFlyElytronBaseProvider.class.getClassLoader();
+ try {
+ implementationClass = Class.forName(getClassName(), false, classLoader);
+ } catch (ClassNotFoundException e) {
+ throw log.noSuchAlgorithmCreateService(getType(), getAlgorithm(), e);
+ }
+ this.implementationClassRef = new WeakReference<>(implementationClass);
+ }
+
+ return implementationClass;
+ }
+
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronDigestProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronDigestProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronDigestProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+import java.util.Collections;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for Digest implementations.
+ *
+ * @author Farah Juma
+ * @deprecated Use org.wildfly.security.digest.WildFlyElytronDigestProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronDigestProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = 2531323760912222262L;
+ private static WildFlyElytronDigestProvider INSTANCE = new WildFlyElytronDigestProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronDigestProvider() {
+ super("WildFlyElytronDigestProvider", "1.0", "WildFly Elytron Digest Provider");
+ putService(new Service(this, "MessageDigest", "SHA-512-256", "org.wildfly.security.digest.SHA512_256MessageDigest", Collections.emptyList(), Collections.emptyMap()));
+ }
+
+ /**
+ * Get the Digest implementations provider instance.
+ *
+ * @return the Digest implementations provider instance
+ */
+ public static WildFlyElytronDigestProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBasicProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBasicProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBasicProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP BASIC authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated Use org.wildfly.security.http.basic.WildFlyElytronHttpBasicProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpBasicProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = 3029961619967561017L;
+ private static WildFlyElytronHttpBasicProvider INSTANCE = new WildFlyElytronHttpBasicProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpBasicProvider() {
+ super("WildFlyElytronHttpBasicProvider", "1.0", "WildFly Elytron HTTP BASIC Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "BASIC", "org.wildfly.security.http.basic.BasicMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ /**
+ * Get the HTTP BASIC authentication mechanism provider instance.
+ *
+ * @return the HTTP BASIC authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpBasicProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBearerProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBearerProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpBearerProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP Bearer authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated use org.wildfly.security.http.bearer.WildFlyElytronHttpBearerProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpBearerProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = -797775107834905210L;
+ private static WildFlyElytronHttpBearerProvider INSTANCE = new WildFlyElytronHttpBearerProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpBearerProvider() {
+ super("WildFlyElytronHttpBearerProvider", "1.0", "WildFly Elytron HTTP Bearer Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "BEARER_TOKEN", "org.wildfly.security.http.bearer.BearerMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ /**
+ * Get the HTTP Bearer authentication mechanism provider instance.
+ *
+ * @return the HTTP Bearer authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpBearerProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpClientCertProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpClientCertProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpClientCertProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP CLIENT_CERT authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated Use org.wildfly.security.http.cert.WildFlyElytronHttpClientCertProvider
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpClientCertProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = -4105163673151031877L;
+ private static WildFlyElytronHttpClientCertProvider INSTANCE = new WildFlyElytronHttpClientCertProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpClientCertProvider() {
+ super("WildFlyElytronHttpClientCertProvider", "1.0", "WildFly Elytron HTTP CLIENT_CERT Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "CLIENT_CERT", "org.wildfly.security.http.cert.ClientCertMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ /**
+ * Get the HTTP CLIENT_CERT authentication mechanism provider instance.
+ *
+ * @return the HTTP CLIENT_CERT authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpClientCertProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpDigestProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpDigestProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpDigestProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+import java.util.Collections;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP DIGEST authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated Use org.wildfly.security.http.digest.WildFlyElytronHttpDigestProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpDigestProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = 7343476391300211681L;
+ private static WildFlyElytronHttpDigestProvider INSTANCE = new WildFlyElytronHttpDigestProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpDigestProvider() {
+ super("WildFlyElytronHttpDigestProvider", "1.0", "WildFly Elytron HTTP DIGEST Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST-SHA-256", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST-SHA-512-256", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+
+ putService(new Service(this, "MessageDigest", "SHA-512-256", "org.wildfly.security.digest.SHA512_256MessageDigest", Collections.emptyList(), Collections.emptyMap()));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "clear", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ }
+
+ /**
+ * Get the HTTP DIGEST authentication mechanism provider instance.
+ *
+ * @return the HTTP DIGEST authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpDigestProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpFormProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpFormProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpFormProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP FORM authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated Use org.wildfly.security.http.form.WildFlyElytronHttpFormProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpFormProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = 3872696509387755963L;
+ private static WildFlyElytronHttpFormProvider INSTANCE = new WildFlyElytronHttpFormProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpFormProvider() {
+ super("WildFlyElytronHttpFormProvider", "1.0", "WildFly Elytron HTTP FORM Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "FORM", "org.wildfly.security.http.form.FormMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ /**
+ * Get the HTTP FORM authentication mechanism provider instance.
+ *
+ * @return the HTTP FORM authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpFormProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpSpnegoProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpSpnegoProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronHttpSpnegoProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2018 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import java.security.Provider;
+
+import org.kohsuke.MetaInfServices;
+
+/**
+ * Provider for the HTTP SPNEGO authentication mechanism.
+ *
+ * @author Farah Juma
+ * @deprecated use org.wildfly.security.http.spnego.WildFlyElytronHttpSpnegoProvider instead
+ */
+@Deprecated
+@MetaInfServices(Provider.class)
+public final class WildFlyElytronHttpSpnegoProvider extends WildFlyElytronBaseProvider {
+
+ private static final long serialVersionUID = 9211317885580156246L;
+ private static WildFlyElytronHttpSpnegoProvider INSTANCE = new WildFlyElytronHttpSpnegoProvider();
+
+ /**
+ * Construct a new instance.
+ */
+ public WildFlyElytronHttpSpnegoProvider() {
+ super("WildFlyElytronHttpSpnegoProvider", "1.0", "WildFly Elytron HTTP SPNEGO Provider");
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "SPNEGO", "org.wildfly.security.http.spnego.SpnegoMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ /**
+ * Get the HTTP SPNEGO authentication mechanism provider instance.
+ *
+ * @return the HTTP SPNEGO authentication mechanism provider instance
+ */
+ public static WildFlyElytronHttpSpnegoProvider getInstance() {
+ return INSTANCE;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronProvider.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronProvider.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/WildFlyElytronProvider.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,330 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security;
+
+import static org.wildfly.security.ElytronMessages.log;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.kohsuke.MetaInfServices;
+
+
+/**
+ * The {@link Provider} implementation covering all security services made available by Elytron.
+ *
+ * @author Darran Lofthouse
+ * @author David M. Lloyd
+ */
+@MetaInfServices(Provider.class)
+@Deprecated
+public class WildFlyElytronProvider extends VersionedProvider {
+
+ private static final long serialVersionUID = 1267015094996624988L;
+
+ private static final String HTTP_SERVER_FACTORY_TYPE = "HttpServerAuthenticationMechanismFactory";
+
+ private static final String SASL_CLIENT_FACTORY_TYPE = "SaslClientFactory";
+
+ private static final String SASL_SERVER_FACTORY_TYPE = "SaslServerFactory";
+
+ private static final String PASSWORD_FACTORY_TYPE = "PasswordFactory";
+
+ private static final String ALG_PARAMS_TYPE = "AlgorithmParameters";
+
+ /**
+ * Default constructor for this security provider.
+ */
+ public WildFlyElytronProvider() {
+ super("WildFlyElytron", "1.0", "WildFly Elytron Provider");
+
+ putHttpAuthenticationMechanismImplementations();
+ putKeyStoreImplementations();
+ putPasswordImplementations();
+ putSaslMechanismImplementations();
+ putCredentialStoreProviderImplementations();
+ putAlgorithmParametersImplementations();
+ putService(new Service(this, "SecretKeyFactory", "1.2.840.113549.1.7.1", "org.wildfly.security.key.RawSecretKeyFactory", Collections.emptyList(), Collections.emptyMap()));
+ putService(new Service(this, "MessageDigest", "SHA-512-256", "org.wildfly.security.digest.SHA512_256MessageDigest", Collections.emptyList(), Collections.emptyMap()));
+ }
+
+ private void putAlgorithmParametersImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+
+ putService(new Service(this, ALG_PARAMS_TYPE, "RSA", "org.wildfly.security.key.RSAParameterSpiImpl", emptyList, emptyMap));
+
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "sun-crypt-md5", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "sun-crypt-md5-bare-salt", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-sha-256", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-sha-512", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-md5", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-256", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-384", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-512", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "digest-sha-512-256", "org.wildfly.security.password.impl.DigestPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-1", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-256", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-384", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "password-salt-digest-sha-512", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-md5", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-1", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-256", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-384", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "salt-password-digest-sha-512", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "crypt-des", "org.wildfly.security.password.impl.SaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "bsd-crypt-des", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "bcrypt", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-1", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-256", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-384", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "scram-sha-512", "org.wildfly.security.password.impl.IteratedSaltedPasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-md5", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha1", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha256", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha384", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ putService(new Service(this, ALG_PARAMS_TYPE, "otp-sha512", "org.wildfly.security.password.impl.OneTimePasswordAlgorithmParametersSpiImpl", emptyList, emptyMap));
+ WildFlyElytronBaseProvider.putMakedAlgorithmParametersImplementations(this::putService, this);
+ }
+
+ private void putKeyStoreImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+
+ putService(new Service(this, "KeyStore", "PasswordFile", "org.wildfly.security.keystore.PasswordKeyStoreSpi", emptyList, emptyMap));
+ }
+
+ private void putHttpAuthenticationMechanismImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "BASIC", "org.wildfly.security.http.basic.BasicMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "CLIENT_CERT", "org.wildfly.security.http.cert.ClientCertMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST-SHA-256", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "DIGEST-SHA-512-256", "org.wildfly.security.http.digest.DigestMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "EXTERNAL", "org.wildfly.security.http.external.ExternalMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "FORM", "org.wildfly.security.http.form.FormMechanismFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "SPNEGO", "org.wildfly.security.http.spnego.SpnegoMechanismFactory", emptyList, emptyMap, true, true));
+
+ putService(new ProviderService(this, HTTP_SERVER_FACTORY_TYPE, "BEARER_TOKEN", "org.wildfly.security.http.bearer.BearerMechanismFactory", emptyList, emptyMap, true, true));
+ }
+
+ private void putPasswordImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "clear", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "sun-crypt-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "sun-crypt-md5-bare-salt", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-md2", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "simple-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "digest-sha-512-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "password-salt-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "salt-password-digest-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "crypt-des", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "bsd-crypt-des", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "bcrypt", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "scram-sha-512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-md5", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha1", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha256", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha384", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ putService(new Service(this, PASSWORD_FACTORY_TYPE, "otp-sha512", "org.wildfly.security.password.impl.PasswordFactorySpiImpl", emptyList, emptyMap));
+ WildFlyElytronBaseProvider.putMakedPasswordImplementations(this::putService, this);
+ }
+
+ private void putSaslMechanismImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "ANONYMOUS", "org.wildfly.security.sasl.anonymous.AnonymousServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-SHA-512", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-SHA-512-256", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-SHA-256", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-SHA-384", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-SHA", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "DIGEST-MD5", "org.wildfly.security.sasl.digest.DigestServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-U-RSA-SHA1-ENC", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-M-RSA-SHA1-ENC", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-U-DSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-M-DSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-U-ECDSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "9798-M-ECDSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "EXTERNAL", "org.wildfly.security.sasl.external.ExternalSaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "GS2-KRB5-PLUS", "org.wildfly.security.sasl.gs2.Gs2SaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "GS2-KRB5", "org.wildfly.security.sasl.gs2.Gs2SaslServerFactory", emptyList, emptyMap, false, true));
+
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "GSSAPI", "org.wildfly.security.sasl.gssapi.GssapiServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "JBOSS-LOCAL-USER", "org.wildfly.security.sasl.localuser.LocalUserServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "OAUTHBEARER", "org.wildfly.security.sasl.oauth2.OAuth2SaslServerFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "OTP", "org.wildfly.security.sasl.otp.OTPSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "PLAIN", "org.wildfly.security.sasl.plain.PlainSaslServerFactory", emptyList, emptyMap, false, true));
+
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-512-PLUS", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-384-PLUS", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-256-PLUS", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-1-PLUS", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-512", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-384", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-256", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_SERVER_FACTORY_TYPE, "SCRAM-SHA-1", "org.wildfly.security.sasl.scram.ScramSaslServerFactory", emptyList, emptyMap, true, true));
+
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "ANONYMOUS", "org.wildfly.security.sasl.anonymous.AnonymousClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-SHA-512", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-SHA-512-256", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-SHA-256", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-SHA-384", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-SHA", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "DIGEST-MD5", "org.wildfly.security.sasl.digest.DigestClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-U-RSA-SHA1-ENC", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-M-RSA-SHA1-ENC", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-U-DSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-M-DSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-U-ECDSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "9798-M-ECDSA-SHA1", "org.wildfly.security.sasl.entity.EntitySaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "EXTERNAL", "org.wildfly.security.sasl.external.ExternalSaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "GS2-KRB5-PLUS", "org.wildfly.security.sasl.gs2.Gs2SaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "GS2-KRB5", "org.wildfly.security.sasl.gs2.Gs2SaslClientFactory", emptyList, emptyMap, false, true));
+
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "GSSAPI", "org.wildfly.security.sasl.gssapi.GssapiClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "JBOSS-LOCAL-USER", "org.wildfly.security.sasl.localuser.LocalUserClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "OAUTHBEARER", "org.wildfly.security.sasl.oauth2.OAuth2SaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "OTP", "org.wildfly.security.sasl.otp.OTPSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "PLAIN", "org.wildfly.security.sasl.plain.PlainSaslClientFactory", emptyList, emptyMap, false, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-512-PLUS", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-384-PLUS", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-256-PLUS", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-1-PLUS", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-512", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-384", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-256", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ putService(new ProviderService(this, SASL_CLIENT_FACTORY_TYPE, "SCRAM-SHA-1", "org.wildfly.security.sasl.scram.ScramSaslClientFactory", emptyList, emptyMap, true, true));
+ }
+
+ private void putCredentialStoreProviderImplementations() {
+ final List emptyList = Collections.emptyList();
+ final Map emptyMap = Collections.emptyMap();
+ putService(new Service(this, "CredentialStore", "KeyStoreCredentialStore", "org.wildfly.security.credential.store.impl.KeyStoreCredentialStore", emptyList, emptyMap));
+ putService(new Service(this, "CredentialStore", "VaultCredentialStore", "org.wildfly.security.credential.store.impl.VaultCredentialStore", emptyList, emptyMap));
+ putService(new Service(this, "CredentialStore", "MapCredentialStore", "org.wildfly.security.credential.store.impl.MapCredentialStore", emptyList, emptyMap));
+ putService(new Service(this, "CredentialStore", "PropertiesCredentialStore", "org.wildfly.security.credential.store.impl.PropertiesCredentialStore", emptyList, emptyMap));
+ }
+
+ class ProviderService extends Service {
+
+ private final boolean withProvider;
+ private final boolean reUsable;
+ private volatile Reference> implementationClassRef;
+ private volatile Reference instance;
+
+ ProviderService(Provider provider, String type, String algorithm, String className, List aliases, Map attributes) {
+ this(provider, type, algorithm, className, aliases, attributes, true, false);
+ }
+
+ ProviderService(Provider provider, String type, String algorithm, String className, List aliases, Map attributes, boolean withProvider, boolean reUsable) {
+ super(provider, type, algorithm, className, aliases, attributes);
+ this.withProvider = withProvider;
+ this.reUsable = reUsable;
+ }
+
+ @Override
+ public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException {
+ if (reUsable) {
+ Reference instance = this.instance;
+ Object response;
+ if (instance == null || (response = instance.get()) == null) {
+ synchronized(this) {
+ instance = this.instance;
+ if (instance == null || (response = instance.get()) == null) {
+ response = withProvider ? newInstance() : super.newInstance(constructorParameter);
+ this.instance = new SoftReference(response);
+ }
+ }
+ }
+
+ return response;
+ }
+
+ return withProvider ? newInstance() : super.newInstance(constructorParameter);
+ }
+
+ private Object newInstance() throws NoSuchAlgorithmException {
+ Class> implementationClass = getImplementationClass();
+
+ try {
+ Constructor> constructor = implementationClass.getConstructor(Provider.class);
+ return constructor.newInstance(WildFlyElytronProvider.this);
+ } catch (Exception e) {
+ throw log.noSuchAlgorithmCreateService(getType(), getAlgorithm(), e);
+ }
+ }
+
+ private Class> getImplementationClass() throws NoSuchAlgorithmException {
+ Reference> implementationClassRef = this.implementationClassRef;
+ Class> implementationClass = implementationClassRef != null ? implementationClassRef.get() : null;
+ if (implementationClass == null) {
+ ClassLoader classLoader = WildFlyElytronProvider.class.getClassLoader();
+ try {
+ implementationClass = Class.forName(getClassName(), false, classLoader);
+ } catch (ClassNotFoundException e) {
+ throw log.noSuchAlgorithmCreateService(getType(), getAlgorithm(), e);
+ }
+ this.implementationClassRef = new WeakReference<>(implementationClass);
+ }
+
+ return implementationClass;
+ }
+
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/AuthenticationException.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/AuthenticationException.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/AuthenticationException.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth;
+
+import java.io.IOException;
+
+/**
+ * An exception indicating that an initial authentication (login) operation has failed.
+ *
+ * @author David M. Lloyd
+ */
+public class AuthenticationException extends IOException {
+
+ private static final long serialVersionUID = -1038330178933137221L;
+
+ /**
+ * Constructs a new {@code org.wildfly.security.auth.AuthenticationException} instance. The message is left blank
+ * ({@code null}), and no cause is specified.
+ */
+ public AuthenticationException() {
+ }
+
+ /**
+ * Constructs a new {@code org.wildfly.security.auth.AuthenticationException} instance with an initial message. No
+ * cause is specified.
+ *
+ * @param msg the message
+ */
+ public AuthenticationException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new {@code org.wildfly.security.auth.AuthenticationException} instance with an initial cause. If a
+ * non-{@code null} cause is specified, its message is used to initialize the message of this {@code
+ * org.wildfly.security.auth.AuthenticationException}; otherwise the message is left blank ({@code null}).
+ *
+ * @param cause the cause
+ */
+ public AuthenticationException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new {@code org.wildfly.security.auth.AuthenticationException} instance with an initial message and
+ * cause.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public AuthenticationException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/ReauthenticationException.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/ReauthenticationException.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/ReauthenticationException.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth;
+
+/**
+ * A run-time exception indicating that a reauthentication was required for an operation, but the reauthentication
+ * failed, preventing the operation from proceeding. Reauthentication can happen when (for example) a persistent
+ * connection is broken and reestablished, or an authentication session was forcibly terminated, or because a backing
+ * system uses an authentication-per-request strategy, or other reasons.
+ *
+ * @author David M. Lloyd
+ */
+public class ReauthenticationException extends SecurityException {
+ private static final long serialVersionUID = 6765807441459168511L;
+
+ /**
+ * Constructs a new {@code ReauthenticationException} instance. The message is left blank ({@code null}), and no
+ * cause is specified.
+ */
+ public ReauthenticationException() {
+ }
+
+ /**
+ * Constructs a new {@code ReauthenticationException} instance with an initial message. No cause is specified.
+ *
+ * @param msg the message
+ */
+ public ReauthenticationException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new {@code ReauthenticationException} instance with an initial cause. If a non-{@code null} cause
+ * is specified, its message is used to initialize the message of this {@code ReauthenticationException}; otherwise
+ * the message is left blank ({@code null}).
+ *
+ * @param cause the cause
+ */
+ public ReauthenticationException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new {@code ReauthenticationException} instance with an initial message and cause.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public ReauthenticationException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/SupportLevel.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/SupportLevel.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/SupportLevel.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,148 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth;
+
+import java.util.EnumSet;
+
+import org.wildfly.common.Assert;
+
+/**
+ * The different support levels.
+ *
+ * @author David M. Lloyd
+ */
+public enum SupportLevel {
+
+ /**
+ * The given credential type is definitely not supported.
+ */
+ UNSUPPORTED,
+ /**
+ * The given credential type may be supported.
+ */
+ POSSIBLY_SUPPORTED,
+ /**
+ * The given credential type is definitely supported.
+ */
+ SUPPORTED,
+ ;
+
+ /**
+ * Determine if this object represents definite support.
+ *
+ * @return {@code true} if this object represents definite support, {@code false} otherwise
+ */
+ public boolean isDefinitelySupported() {
+ return this == SUPPORTED;
+ }
+
+ /**
+ * Determine if this object represents possible or definite support.
+ *
+ * @return {@code true} if this object represents possible or definite support, {@code false} otherwise
+ */
+ public boolean mayBeSupported() {
+ return this != UNSUPPORTED;
+ }
+
+ /**
+ * Determine if this object represents definite lack of support.
+ *
+ * @return {@code true} if this object represents definite lack of support, {@code false} otherwise
+ */
+ public boolean isNotSupported() {
+ return this == UNSUPPORTED;
+ }
+
+ private static final int fullSize = values().length;
+
+ /**
+ * Determine whether the given set is fully populated (or "full"), meaning it contains all possible values.
+ *
+ * @param set the set
+ *
+ * @return {@code true} if the set is full, {@code false} otherwise
+ */
+ public static boolean isFull(final EnumSet set) {
+ return set != null && set.size() == fullSize;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final SupportLevel v1) {
+ return this == v1;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ * @param v2 the second instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final SupportLevel v1, final SupportLevel v2) {
+ return this == v1 || this == v2;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ * @param v2 the second instance
+ * @param v3 the third instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final SupportLevel v1, final SupportLevel v2, final SupportLevel v3) {
+ return this == v1 || this == v2 || this == v3;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param values the possible values
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final SupportLevel... values) {
+ if (values != null) for (SupportLevel value : values) {
+ if (this == value) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the maximum support level between two candidates.
+ *
+ * @param o1 the first support level (must not be {@code null})
+ * @param o2 the second support level (must not be {@code null})
+ * @return the maximum support level (not {@code null})
+ */
+ public static SupportLevel max(SupportLevel o1, SupportLevel o2) {
+ Assert.checkNotNullParam("o1", o1);
+ Assert.checkNotNullParam("o2", o2);
+ return o1.compareTo(o2) < 0 ? o2 : o1;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AbstractCredentialCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AbstractCredentialCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AbstractCredentialCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,236 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2017 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.function.Function;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.server._private.ElytronMessages;
+import org.wildfly.security.credential.AlgorithmCredential;
+import org.wildfly.security.credential.Credential;
+
+/**
+ * Abstract base class for credential callbacks.
+ *
+ * @author David M. Lloyd
+ */
+public abstract class AbstractCredentialCallback implements ExtendedCallback {
+
+ private final Class extends Credential> credentialType;
+ private final String algorithm;
+ private final AlgorithmParameterSpec parameterSpec;
+ private Credential credential;
+
+ AbstractCredentialCallback(final Class extends Credential> credentialType, final String algorithm, final AlgorithmParameterSpec parameterSpec) {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ if (parameterSpec != null) Assert.checkNotNullParam("algorithm", algorithm);
+ this.algorithm = algorithm;
+ this.credentialType = credentialType;
+ this.parameterSpec = parameterSpec;
+ }
+
+ /**
+ * Get the acquired credential.
+ *
+ * @return the acquired credential, or {@code null} if it wasn't set yet.
+ */
+ public Credential getCredential() {
+ return credential;
+ }
+
+ /**
+ * Get the acquired credential, if it is set and of the given type, and if so, return the credential cast to the type.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param the credential type
+ * @return the credential, or {@code null} if the criteria wasn't met
+ */
+ public C getCredential(Class credentialType) {
+ return applyToCredential(credentialType, Function.identity());
+ }
+
+ /**
+ * Get the acquired credential, if it is set and of the given type and algorithm, and if so, return the credential cast to the type.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param the credential type
+ * @return the credential, or {@code null} if the criteria are not met
+ */
+ public C getCredential(Class credentialType, String algorithmName) {
+ return applyToCredential(credentialType, algorithmName, Function.identity());
+ }
+
+ /**
+ * Get the acquired credential, if it is set and of the given type, algorithm, and parameters, and if so, return the credential cast to the type.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param parameterSpec the parameter specification to match, or {@code null} if any parameters are allowed or parameters are not used by
+ * the credential type
+ * @param the credential type
+ * @return the credential, or {@code null} if the criteria are not met
+ */
+ public C getCredential(Class credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec) {
+ return applyToCredential(credentialType, algorithmName, parameterSpec, Function.identity());
+ }
+
+ /**
+ * Apply the given function to the acquired credential, if it is set and of the given type. By calling this method,
+ * it is possible to apply transformations to the stored credential without failing if the credential was not set.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param function the function to apply (must not be {@code null})
+ * @param the credential type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToCredential(Class credentialType, Function function) {
+ final Credential credential = this.credential;
+ return credential == null ? null : credential.castAndApply(credentialType, function);
+ }
+
+ /**
+ * Apply the given function to the acquired credential, if it is set and of the given type and algorithm. By calling this method,
+ * it is possible to apply transformations to the stored credential without failing if the credential was not set.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param function the function to apply (must not be {@code null})
+ * @param the credential type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToCredential(Class credentialType, String algorithmName, Function function) {
+ final Credential credential = this.credential;
+ return credential == null ? null : credential.castAndApply(credentialType, algorithmName, function);
+ }
+
+ /**
+ * Apply the given function to the acquired credential, if it is set and of the given type and algorithm. By calling this method,
+ * it is possible to apply transformations to the stored credential without failing if the credential was not set.
+ *
+ * @param credentialType the credential type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param parameterSpec the parameter specification to match, or {@code null} if any parameters are allowed or parameters are not used by
+ * the credential type
+ * @param function the function to apply (must not be {@code null})
+ * @param the credential type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToCredential(Class credentialType, String algorithmName, AlgorithmParameterSpec parameterSpec, Function function) {
+ final Credential credential = this.credential;
+ return credential == null ? null : credential.castAndApply(credentialType, algorithmName, parameterSpec, function);
+ }
+
+ /**
+ * Set the credential. The credential must be of the supported type and algorithm.
+ *
+ * @param credential the credential, or {@code null} to indicate that no credential is available
+ * @throws IllegalArgumentException if the given credential is not supported
+ */
+ public void setCredential(final Credential credential) {
+ if (credential != null && ! isCredentialSupported(credential)) {
+ throw ElytronMessages.log.credentialNotSupported();
+ }
+ this.credential = credential;
+ }
+
+ /**
+ * Determine whether the given credential type is supported. Will be {@code false} if the credential type requires
+ * an algorithm name; in this case, use {@link #isCredentialTypeSupported(Class, String)} instead.
+ *
+ * @param credentialType the credential type (must not be {@code null})
+ * @return {@code true} if the credential type is supported, {@code false} otherwise
+ */
+ public boolean isCredentialTypeSupported(final Class extends Credential> credentialType) {
+ return isCredentialTypeSupported(credentialType, null);
+ }
+
+ /**
+ * Determine whether the given credential type is supported for the given algorithm name.
+ *
+ * @param credentialType the credential type (must not be {@code null})
+ * @param algorithmName the algorithm name, or {@code null} to indicate that no algorithm name will be available
+ * @return {@code true} if the credential type is supported, {@code false} otherwise
+ */
+ public boolean isCredentialTypeSupported(final Class extends Credential> credentialType, final String algorithmName) {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ return this.credentialType.isAssignableFrom(credentialType) && (algorithm == null || AlgorithmCredential.class.isAssignableFrom(credentialType) && algorithm.equals(algorithmName));
+ }
+
+ /**
+ * Determine whether the given credential type is supported for the given algorithm name.
+ *
+ * @param credentialType the credential type (must not be {@code null})
+ * @param algorithmName the algorithm name, or {@code null} to indicate that no algorithm name will be available
+ * @param parameterSpec the parameters, or {@code null} if no parameters are present in the credential
+ * @return {@code true} if the credential type is supported, {@code false} otherwise
+ */
+ public boolean isCredentialTypeSupported(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ return isCredentialTypeSupported(credentialType, algorithmName) && (this.parameterSpec == null || this.parameterSpec.equals(parameterSpec));
+ }
+
+ /**
+ * Determine whether the given credential can be set on this callback.
+ *
+ * @param credential the credential (must not be {@code null})
+ * @return {@code true} if the credential matches the type and optional algorithm of this callback, {@code false} otherwise
+ */
+ public boolean isCredentialSupported(final Credential credential) {
+ Assert.checkNotNullParam("credential", credential);
+ return credential.castAs(credentialType, algorithm, parameterSpec) != null;
+ }
+
+ /**
+ * Get the supported credential type.
+ *
+ * @return the supported credential type (not {@code null})
+ */
+ public Class extends Credential> getCredentialType() {
+ return credentialType;
+ }
+
+ /**
+ * Get the algorithm name, if any.
+ *
+ * @return the algorithm name, or {@code null} if any algorithm is suitable or the credential
+ * type does not use algorithm names
+ */
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ /**
+ * Get the parameter specification, if any.
+ *
+ * @return the parameter specification, or {@code null} if any parameters are suitable or the credential type
+ * does not use parameters
+ */
+ public AlgorithmParameterSpec getParameterSpec() {
+ return parameterSpec;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AnonymousAuthorizationCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AnonymousAuthorizationCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AnonymousAuthorizationCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.Serializable;
+
+/**
+ * A callback to authorize anonymous authentication.
+ *
+ * @author David M. Lloyd
+ */
+public final class AnonymousAuthorizationCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = -6532813145396004679L;
+
+ /**
+ * @serial The authorization information from the client.
+ */
+ private final String authorizationInfo;
+ /**
+ * @serial The authorization result flag.
+ */
+ private boolean authorized;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param authorizationInfo the authorization information string from the client
+ */
+ public AnonymousAuthorizationCallback(final String authorizationInfo) {
+ this.authorizationInfo = authorizationInfo;
+ }
+
+ /**
+ * Get the authorization name string from the client. This name is only informative and must not be used
+ * for authentication purposes.
+ *
+ * @return the authorization name string from the client
+ */
+ public String getAuthorizationInfo() {
+ return authorizationInfo;
+ }
+
+ /**
+ * Determine whether anonymous access was allowed by the callback handler.
+ *
+ * @return {@code true} if anonymous authentication was allowed, {@code false} otherwise
+ */
+ public boolean isAuthorized() {
+ return authorized;
+ }
+
+ /**
+ * Set whether anonymous access is allowed.
+ *
+ * @param authorized {@code true} if anonymous access is allowed, {@code false} otherwise
+ */
+ public void setAuthorized(final boolean authorized) {
+ this.authorized = authorized;
+ }
+
+ public boolean isOptional() {
+ return false;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationCompleteCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationCompleteCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationCompleteCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.Serializable;
+
+/**
+ * An optional callback indicating the success or failure of the authentication operation. When this callback is
+ * received, the callback handler may free any resources that were required to perform the authentication. This
+ * callback should always be sent to the callback handler last.
+ *
+ * @author David M. Lloyd
+ */
+public final class AuthenticationCompleteCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = -8336218311376736914L;
+
+ public static final AuthenticationCompleteCallback SUCCEEDED = new AuthenticationCompleteCallback(true);
+
+ public static final AuthenticationCompleteCallback FAILED = new AuthenticationCompleteCallback(false);
+
+ /**
+ * @serial The flag indicating whether the authentication was successful.
+ */
+ private final boolean success;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param success {@code true} if the authentication was successful, {@code false} otherwise
+ */
+ private AuthenticationCompleteCallback(final boolean success) {
+ this.success = success;
+ }
+
+ /**
+ * Determine whether authentication succeeded. Always returns the opposite of {@link #failed()}.
+ *
+ * @return {@code true} if authentication succeeded, {@code false} otherwise
+ */
+ public boolean succeeded() {
+ return success;
+ }
+
+ /**
+ * Determine whether authentication failed. Always returns the opposite of {@link #succeeded()}.
+ *
+ * @return {@code true} if the authentication failed, {@code false} otherwise
+ */
+ public boolean failed() {
+ return ! success;
+ }
+
+ /**
+ * Replace the deserialized instance with the sppropriate singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ Object readResolve() {
+ return success ? SUCCEEDED : FAILED;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationConfigurationCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationConfigurationCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AuthenticationConfigurationCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2023 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.callback;
+
+
+/**
+ * A {@link javax.security.auth.callback.Callback} to inform a server authentication context of configured mechanism properties.
+ *
+ * As an informational {@code Callback} it is optional for the {@code CallbackHandler} to handle this.
+ *
+ */
+public class AuthenticationConfigurationCallback implements ExtendedCallback{
+
+ /**
+ * Property of the SASL EXTERNAL mechanism that indicates whether a certificate should be verified against the security realm.
+ */
+ private boolean saslSkipCertificateVerification;
+
+ public boolean getSaslSkipCertificateVerification() {
+ return this.saslSkipCertificateVerification;
+ }
+
+ public void setSaslSkipCertificateVerification(boolean skipCertificateVerification) {
+ this.saslSkipCertificateVerification = skipCertificateVerification;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AvailableRealmsCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AvailableRealmsCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/AvailableRealmsCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.server.SecurityRealm;
+
+/**
+ * A callback used to query a server participant for the names of realms that it is prepared to offer. Note that the
+ * authentication mechanism realm concept is not directly related to the Elytron {@linkplain SecurityRealm security realm concept}.
+ *
+ * @author David M. Lloyd
+ */
+public final class AvailableRealmsCallback implements ExtendedCallback {
+ private String[] realmNames;
+
+ /**
+ * Construct a new instance.
+ */
+ public AvailableRealmsCallback() {
+ }
+
+ /**
+ * Get the array of realm names that was set.
+ *
+ * @return the realm names array
+ */
+ public String[] getRealmNames() {
+ return realmNames;
+ }
+
+ /**
+ * Set the realm names. None of the realm names may be {@code null}. The array is not copied, so care must
+ * be taken to avoid modifying the realm array after it is set.
+ *
+ * @param realmNames the realm names (may not be {@code null}, may not contain {@code null})
+ */
+ public void setRealmNames(final String... realmNames) {
+ Assert.checkNotNullParam("realmNames", realmNames);
+ for (int i = 0, realmNamesLength = realmNames.length; i < realmNamesLength; i++) {
+ Assert.checkNotNullArrayParam("realmNames", i, realmNames[i]);
+ }
+ this.realmNames = realmNames;
+ }
+
+ public boolean isOptional() {
+ return true;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CachedIdentityAuthorizeCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CachedIdentityAuthorizeCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CachedIdentityAuthorizeCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,232 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.principal.NamePrincipal;
+import org.wildfly.security.auth.server.SecurityDomain;
+import org.wildfly.security.auth.server.SecurityIdentity;
+import org.wildfly.security.cache.CachedIdentity;
+import org.wildfly.security.cache.IdentityCache;
+
+import java.security.Principal;
+import java.util.function.Function;
+
+import static org.wildfly.common.Assert.checkNotNullParam;
+
+/**
+ * A callback that is capable of perform authorization based on the identities managed by an {@link IdentityCache}.
+ *
+ *
This callback can be used in two ways:
+ *
+ *
+ * As an alternative to {@link javax.security.sasl.AuthorizeCallback}. As a result, the identity (if successfully authorized) will be cached
+ * To perform a lookup in the cache and authorize the cached identity locally
+ *
+ *
+ * @author Pedro Igor
+ */
+public class CachedIdentityAuthorizeCallback implements ExtendedCallback {
+
+ private final Function identityCache;
+ private final boolean localCache;
+ private Principal principal;
+ private boolean authorized;
+ private SecurityDomain securityDomain;
+
+ /**
+ * Creates a new instance in order to authorize identities managed by the given identityCache
.
+ *
+ * @param identityCache the identity cache
+ */
+ public CachedIdentityAuthorizeCallback(IdentityCache identityCache) {
+ this(identityCache, false);
+ }
+
+ /**
+ * Creates a new instance in order to authorize identities managed by the given identityCache
.
+ *
+ * @param identityCache the identity cache
+ * @param localCache if true, indicates that authorization should be based on the given {@code identityCache} only. In case the mechanism
+ * performing the authorization is wrapped by another one that provides a top-level cache (eg.: SSO), only the given
+ * {@code identityCache} will be considered.
+ */
+ public CachedIdentityAuthorizeCallback(IdentityCache identityCache, boolean localCache) {
+ this(securityDomain1 -> identityCache, localCache);
+ }
+
+ /**
+ * Creates a new instance in order to authorize identities managed by the given identityCache
.
+ *
+ *
This constructor can be used to perform caching operations (e.g.: put, get and remove) in the context of a {@link SecurityDomain}.
+ *
+ * @param identityCache a function that creates an {@link IdentityCache} given a {@link SecurityDomain}
+ * @param localCache if true, indicates that authorization should be based on the given {@code identityCache} only. In case the mechanism
+ * performing the authorization is wrapped by another one that provides a top-level cache (eg.: SSO), only the given
+ * {@code identityCache} will be considered.
+ */
+ public CachedIdentityAuthorizeCallback(Function identityCache, boolean localCache) {
+ checkNotNullParam("identityCache", identityCache);
+ this.identityCache = identityCache;
+ this.localCache = localCache;
+ }
+
+ /**
+ * Creates a new instance to authenticate, authorize and cache the identity associated with the given name
.
+ *
+ * @param name the name associated with the identity
+ * @param identityCache the identity cache
+ */
+ public CachedIdentityAuthorizeCallback(String name, IdentityCache identityCache) {
+ this(new NamePrincipal(name), identityCache);
+ }
+
+ /**
+ * Creates a new instance to authenticate, authorize and cache the identity associated with the given principal
.
+ *
+ * @param principal the principal associated with the identity
+ * @param identityCache the identity cache
+ * @param localCache if true, indicates that authorization should be based on the given {@code identityCache} only. In case the mechanism
+ * performing the authorization is wrapped by another one that provides a top-level cache (eg.: SSO), only the given
+ * {@code identityCache} will be considered.
+ */
+ public CachedIdentityAuthorizeCallback(Principal principal, IdentityCache identityCache, boolean localCache) {
+ this(principal, securityDomain -> identityCache, localCache);
+ }
+
+ /**
+ * Creates a new instance to authenticate, authorize and cache the identity associated with the given principal
.
+ *
+ * @param principal the principal associated with the identity
+ * @param identityCache the identity cache
+ */
+ public CachedIdentityAuthorizeCallback(Principal principal, IdentityCache identityCache) {
+ this(principal, securityDomain -> identityCache, false);
+ }
+
+ /**
+ * Creates a new instance to authenticate, authorize and cache the identity associated with the given principal
.
+ *
+ *
This constructor can be used to perform caching operations (e.g.: put, get and remove) in the context of a {@link SecurityDomain}.
+ *
+ * @param principal the principal associated with the identity
+ * @param identityCache a function that creates an {@link IdentityCache} given a {@link SecurityDomain}
+ * @param localCache if true, indicates that authorization should be based on the given {@code identityCache} only. In case the mechanism
+ * performing the authorization is wrapped by another one that provides a top-level cache (eg.: SSO), only the given
+ * {@code identityCache} will be considered.
+ */
+ public CachedIdentityAuthorizeCallback(Principal principal, Function identityCache, boolean localCache) {
+ checkNotNullParam("principal", principal);
+ checkNotNullParam("identityCache", identityCache);
+ this.principal = principal;
+ this.identityCache = identityCache;
+ this.localCache = localCache;
+ }
+
+ /**
+ * Indicates if a cached identity was successfully authorized.
+ *
+ * @return true if the cached identity was successfully authorized. Otherwise, false
+ */
+ public boolean isAuthorized() {
+ return authorized;
+ }
+
+ /**
+ * Authorizes and caches the given securityIdentity
.
+ *
+ * @param securityIdentity the identity to authorize and cache. If null, the corresponding identity will be removed from the cache
+ */
+ public void setAuthorized(SecurityIdentity securityIdentity) {
+ authorized = securityIdentity != null;
+ if (authorized) {
+ createDomainCache().put(securityIdentity);
+ } else {
+ createDomainCache().remove();
+ }
+ }
+
+ /**
+ * Returns the {@link Principal} representing the cached identity.
+ *
+ * @return the principal (not {@code null})
+ */
+ public Principal getPrincipal() {
+ CachedIdentity cachedIdentity = createDomainCache().get();
+ if (cachedIdentity != null) {
+ return new NamePrincipal(cachedIdentity.getName());
+ }
+ return null;
+ }
+
+ /**
+ * Returns the authorization {@link Principal}.
+ *
+ * @return the principal (not {@code null})
+ */
+ public Principal getAuthorizationPrincipal() {
+ return this.principal;
+ }
+
+ /**
+ * Returns a cached {@link SecurityIdentity}, if present in the cache.
+ *
+ * @return the cached identity or null if there is no entry in the cache
+ */
+ public SecurityIdentity getIdentity() {
+ CachedIdentity cachedIdentity = createDomainCache().get();
+ if (cachedIdentity != null) {
+ return cachedIdentity.getSecurityIdentity();
+ }
+ return null;
+ }
+
+ /**
+ * Indicates if authorization decisions should be performed based on the given {@link IdentityCache} only.
+ *
+ * @return true indicating that authorization decisions should be performed based on the given {@link IdentityCache} only. Otherwise, false
+ */
+ public boolean isLocalCache() {
+ return localCache;
+ }
+
+ /**
+ * Set the current {@link SecurityDomain} in order to obtain identities from the cache
+ *
+ * @param securityDomain the current security domain
+ */
+ public void setSecurityDomain(SecurityDomain securityDomain) {
+ Assert.checkNotNullParam("securityDomain", securityDomain);
+ this.securityDomain = securityDomain;
+ }
+
+ @Override
+ public boolean isOptional() {
+ return false;
+ }
+
+ @Override
+ public boolean needsInformation() {
+ return false;
+ }
+
+ private IdentityCache createDomainCache() {
+ return this.identityCache.apply(securityDomain);
+ }
+}
\ No newline at end of file
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CallbackUtil.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CallbackUtil.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CallbackUtil.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * Helper utility methods for callback handlers.
+ *
+ * @author David M. Lloyd
+ */
+public final class CallbackUtil {
+
+ private CallbackUtil() {
+ }
+
+ /**
+ * Determine whether a callback is optional.
+ *
+ * @param callback the callback
+ * @return {@code true} if it is optional, {@code false} if it is not optional or optionality could not be determined
+ */
+ public static boolean isOptional(Callback callback) {
+ return callback instanceof ExtendedCallback && ((ExtendedCallback) callback).isOptional();
+ }
+
+ /**
+ * A utility to handle a callback which is unsupported. Optional callbacks will be ignored, otherwise the
+ * exception will be thrown. In the case of optional callbacks, this method will return.
+ *
+ * @param callback the callback which is not supported
+ * @throws UnsupportedCallbackException if the callback is not optional
+ */
+ public static void unsupported(Callback callback) throws UnsupportedCallbackException {
+ if (! isOptional(callback)) {
+ throw new FastUnsupportedCallbackException(callback);
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ChannelBindingCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ChannelBindingCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ChannelBindingCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.Serializable;
+
+/**
+ * A callback used to establish the channel binding for a security mechanism which supports it. Both the binding type
+ * and data must be set, otherwise no channel binding will be established. The channel binding type should be one of
+ * the types described in IANA's
+ * channel binding type registry .
+ *
+ * @author David M. Lloyd
+ */
+public final class ChannelBindingCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = 779300207924589036L;
+
+ /**
+ * @serial The channel binding type.
+ */
+ private String bindingType;
+ /**
+ * @serial The channel binding data.
+ */
+ private byte[] bindingData;
+
+ /**
+ * Construct a new instance.
+ */
+ public ChannelBindingCallback() {
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+
+ /**
+ * Get the selected channel binding type.
+ *
+ * @return the selected channel binding type
+ */
+ public String getBindingType() {
+ return bindingType;
+ }
+
+ /**
+ * Get the opaque channel binding data. This data may come from the connection negotiation or from another security
+ * layer.
+ *
+ * @return the opaque channel binding data
+ */
+ public byte[] getBindingData() {
+ return bindingData;
+ }
+
+ /**
+ * Set the selected channel binding type. The type should be one registered with
+ * IANA .
+ *
+ * @param bindingType the selected channel binding type
+ */
+ public void setBindingType(final String bindingType) {
+ this.bindingType = bindingType;
+ }
+
+ /**
+ * Set the channel binding data. This data may come from the connection negotiation or from another security layer.
+ *
+ * @param bindingData the channel binding data
+ */
+ public void setBindingData(final byte[] bindingData) {
+ this.bindingData = bindingData;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.wildfly.security.credential.Credential;
+
+/**
+ * A callback used to acquire credentials. On the client side of an authentication mechanism, the callback handler is
+ * required to supply a credential for use in outbound authentication. On the server side, the callback handler is
+ * required to supply a credential for use in inbound authentication, possibly for both verification as well as establishing
+ * authentication parameters.
+ *
+ * This callback must be handled if a default credential was not supplied. The callback
+ * handler is expected to provide a credential to this callback if one is not present. If no credential is available,
+ * {@code null} is set, and authentication may fail. If an unsupported credential type is set, an exception is thrown.
+ *
+ * @author David M. Lloyd
+ */
+public final class CredentialCallback extends AbstractCredentialCallback {
+
+ /**
+ * Construct a new instance.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ * @param algorithm the algorithm name, or {@code null} if any algorithm is suitable or the credential
+ * type does not use algorithm names
+ * @param parameterSpec the parameters to match, or {@code null} if any parameters are acceptable or the credential
+ * type does not support parameters
+ */
+ public CredentialCallback(final Class extends Credential> credentialType, final String algorithm, final AlgorithmParameterSpec parameterSpec) {
+ super(credentialType, algorithm, parameterSpec);
+ }
+
+ /**
+ * Construct a new instance which accepts any parameters.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ * @param algorithm the algorithm name, or {@code null} if any algorithm is suitable or the credential
+ * type does not use algorithm names
+ */
+ public CredentialCallback(final Class extends Credential> credentialType, final String algorithm) {
+ this(credentialType, algorithm, null);
+ }
+
+ /**
+ * Construct a new instance which accepts any algorithm name or parameters.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ */
+ public CredentialCallback(final Class extends Credential> credentialType) {
+ this(credentialType, null, null);
+ }
+
+ public boolean isOptional() {
+ return getCredential() != null;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialUpdateCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialUpdateCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/CredentialUpdateCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.credential.Credential;
+
+/**
+ * A callback to inform the callback handler of a credential change.
+ *
+ * @author Farah Juma
+ */
+public final class CredentialUpdateCallback implements ExtendedCallback {
+
+ private final Credential credential;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param credential the new credential
+ */
+ public CredentialUpdateCallback(final Credential credential) {
+ Assert.checkNotNullParam("credential", credential);
+ this.credential = credential;
+ }
+
+ /**
+ * Get the new credential.
+ *
+ * @return the new credential
+ */
+ public Credential getCredential() {
+ return credential;
+ }
+
+ /**
+ * Get the new credential, if it is of the given credential class.
+ *
+ * @param credentialClass the credential class
+ * @param the credential type
+ * @return the credential, or {@code null} if it is not of the given type
+ */
+ public C getCredential(final Class credentialClass) {
+ final Credential credential = this.credential;
+ return credentialClass.isInstance(credential) ? credentialClass.cast(credential) : null;
+ }
+
+ public boolean isOptional() {
+ return false;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceDecodePrincipalCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceDecodePrincipalCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceDecodePrincipalCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,107 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2019 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.callback;
+
+import java.util.function.Function;
+
+import javax.security.auth.callback.Callback;
+
+import org.wildfly.security.evidence.Evidence;
+
+/**
+ * A server-side {@link Callback} to pass the decoded evidence principal from the callback handler
+ * to the authentication mechanism.
+ *
+ * @author Farah Juma
+ * @since 1.10.0
+ */
+public class EvidenceDecodePrincipalCallback implements ExtendedCallback {
+
+ private final Evidence evidence;
+
+ /**
+ * Construct a new instance of this {@link Callback}.
+ *
+ * @param evidence the evidence to be decoded
+ */
+ public EvidenceDecodePrincipalCallback(final Evidence evidence) {
+ this.evidence = evidence;
+ }
+
+ /**
+ * Get the evidence being decoded.
+ *
+ * @return the evidence being decoded
+ */
+ public Evidence getEvidence() {
+ return evidence;
+ }
+
+ /**
+ * Get the acquired evidence, if it is set and of the given type, and if so, return the evidence cast to the type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param the evidence type
+ * @return the evidence, or {@code null} if the criteria wasn't met
+ */
+ public C getEvidence(Class evidenceType) {
+ return applyToEvidence(evidenceType, Function.identity());
+ }
+
+ /**
+ * Get the acquired evidence, if it is set and of the given type and algorithm, and if so, return the evidence cast to the type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param the evidence type
+ * @return the evidence, or {@code null} if the criteria are not met
+ */
+ public C getEvidence(Class evidenceType, String algorithmName) {
+ return applyToEvidence(evidenceType, algorithmName, Function.identity());
+ }
+
+ /**
+ * Apply the given function to the acquired evidence, if it is set and of the given type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param function the function to apply (must not be {@code null})
+ * @param the evidence type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToEvidence(Class evidenceType, Function function) {
+ final Evidence evidence = this.evidence;
+ return evidence == null ? null : evidence.castAndApply(evidenceType, function);
+ }
+
+ /**
+ * Apply the given function to the acquired evidence, if it is set and of the given type and algorithm.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param function the function to apply (must not be {@code null})
+ * @param the evidence type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToEvidence(Class evidenceType, String algorithmName, Function function) {
+ final Evidence evidence = this.evidence;
+ return evidence == null ? null : evidence.castAndApply(evidenceType, algorithmName, function);
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceVerifyCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceVerifyCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/EvidenceVerifyCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,140 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.callback;
+
+import java.util.function.Function;
+
+import org.wildfly.security.evidence.Evidence;
+
+import javax.security.auth.callback.Callback;
+
+/**
+ * A {@link Callback} for use where credential verification is required.
+ *
+ * @author Darran Lofthouse
+ */
+public class EvidenceVerifyCallback implements ExtendedCallback {
+
+ private final Evidence evidence;
+ private boolean verified;
+
+ /**
+ * Construct a new instance of this {@link Callback}.
+ *
+ * @param evidence the evidence to be verified
+ */
+ public EvidenceVerifyCallback(final Evidence evidence) {
+ this.evidence = evidence;
+ }
+
+ /**
+ * Get the evidence being verified.
+ *
+ * @return the evidence being verified
+ */
+ public Evidence getEvidence() {
+ return evidence;
+ }
+
+ /**
+ * Get the acquired evidence, if it is set and of the given type, and if so, return the evidence cast to the type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param the evidence type
+ * @return the evidence, or {@code null} if the criteria wasn't met
+ */
+ public C getEvidence(Class evidenceType) {
+ return applyToEvidence(evidenceType, Function.identity());
+ }
+
+ /**
+ * Get the acquired evidence, if it is set and of the given type and algorithm, and if so, return the evidence cast to the type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param the evidence type
+ * @return the evidence, or {@code null} if the criteria are not met
+ */
+ public C getEvidence(Class evidenceType, String algorithmName) {
+ return applyToEvidence(evidenceType, algorithmName, Function.identity());
+ }
+
+ /**
+ * Apply the given function to the acquired evidence, if it is set and of the given type.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param function the function to apply (must not be {@code null})
+ * @param the evidence type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToEvidence(Class evidenceType, Function function) {
+ final Evidence evidence = this.evidence;
+ return evidence == null ? null : evidence.castAndApply(evidenceType, function);
+ }
+
+ /**
+ * Apply the given function to the acquired evidence, if it is set and of the given type and algorithm.
+ *
+ * @param evidenceType the evidence type class (must not be {@code null})
+ * @param algorithmName the algorithm name
+ * @param function the function to apply (must not be {@code null})
+ * @param the evidence type
+ * @param the return type
+ * @return the result of the function, or {@code null} if the criteria are not met
+ */
+ public R applyToEvidence(Class evidenceType, String algorithmName, Function function) {
+ final Evidence evidence = this.evidence;
+ return evidence == null ? null : evidence.castAndApply(evidenceType, algorithmName, function);
+ }
+
+ /**
+ * Set if the evidence referenced here has been verified.
+ *
+ * @param verified the verification state of the evidence
+ */
+ public void setVerified(final boolean verified) {
+ this.verified = verified;
+ }
+
+ /**
+ * Get the verification state for the evidence referenced here.
+ *
+ * @return {@code true} if the evidence has been verified, {@code false} otherwise
+ */
+ public boolean isVerified() {
+ return verified;
+ }
+
+ /**
+ * This {@link Callback} is not optional as verification is required.
+ */
+ @Override
+ public boolean isOptional() {
+ return false;
+ }
+
+ /**
+ * This {@link Callback} needs to know if evidence validation was successful.
+ */
+ @Override
+ public boolean needsInformation() {
+ return true;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExclusiveNameCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExclusiveNameCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExclusiveNameCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.NameCallback;
+
+/**
+ * A variation on {@code NameCallback} which allows exclusive access to the backing identity to be requested.
+ *
+ * @author Farah Juma
+ */
+public class ExclusiveNameCallback extends NameCallback implements ExtendedCallback {
+
+ private static final long serialVersionUID = 3332866436399055886L;
+
+ /**
+ * @serial A flag indicating whether exclusive access to the backing identity is required.
+ */
+ private final boolean needsExclusiveAccess;
+
+ /**
+ * @serial A flag indicating whether exclusive access to the backing identity was granted.
+ */
+ private boolean exclusiveAccess;
+
+ /**
+ * @serial A flag indicating whether the callback is optional.
+ */
+ private final boolean optional;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the text prompt (must not be {@code null})
+ * @param needsExclusiveAccess {@code true} if exclusive access to the backing identity is required
+ * @param optional {@code true} if the support for the callback is optional
+ */
+ public ExclusiveNameCallback(final String prompt, final boolean needsExclusiveAccess, final boolean optional) {
+ super(prompt);
+ this.needsExclusiveAccess = needsExclusiveAccess;
+ this.optional = optional;
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the text prompt (must not be {@code null})
+ * @param defaultName the name to be used as the default name displayed with the prompt
+ * @param needsExclusiveAccess {@code true} if exclusive access to the backing identity is required
+ * @param optional {@code true} if the support for the callback is optional
+ */
+ public ExclusiveNameCallback(final String prompt, final String defaultName, final boolean needsExclusiveAccess, final boolean optional) {
+ super(prompt, defaultName);
+ this.needsExclusiveAccess = needsExclusiveAccess;
+ this.optional = optional;
+ }
+
+ /**
+ * Determine if exclusive access to the backing identity is required.
+ *
+ * @return {@code true} if exclusive access to the backing identity is required, {@code false} otherwise
+ */
+ public boolean needsExclusiveAccess() {
+ return needsExclusiveAccess;
+ }
+
+ /**
+ * Determine if exclusive access to the backing identity was granted.
+ *
+ * @return {@code true} if exclusive access to the backing identity was granted, {@code false} otherwise
+ */
+ public boolean hasExclusiveAccess() {
+ return exclusiveAccess;
+ }
+
+ /**
+ * Set whether exclusive access to the backing identity was granted.
+ *
+ * @param exclusiveAccess {@code true} if exclusive access to the backing identity was granted, {@code false} otherwise
+ */
+ public void setExclusiveAccess(final boolean exclusiveAccess) {
+ this.exclusiveAccess = exclusiveAccess;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.Callback;
+
+/**
+ * A callback which provides extended information about its usage.
+ *
+ * For example, the following code can be used to detect an optional callback instead of failing if the callback is
+ * unrecognized:
+ *
{@code
+ if (callback instanceof ExtendedCallback && ((ExtendedCallback) callback).isOptional()) {
+ // The callback is harmless
+ return;
+ }
+ // Let the caller know that we failed to support this callback
+ throw new UnsupportedCallbackException(callback);
+ * }
+ * Or, the utility method in {@link CallbackUtil} can be used:
+ * {@code
+ CallbackUtils.unsupported(callback);
+ * }
+ */
+public interface ExtendedCallback extends Callback {
+
+ /**
+ * Determine if this callback is optional.
+ *
+ * @return {@code true} if the callback is optional, {@code false} if it is mandatory
+ */
+ default boolean isOptional() {
+ return true;
+ }
+
+ /**
+ * Determine if this callback is requesting information.
+ *
+ * @return {@code true} if the callback is requesting information, {@code false} if it is only providing information
+ */
+ default boolean needsInformation() {
+ return false;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedChoiceCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedChoiceCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ExtendedChoiceCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.ChoiceCallback;
+
+/**
+ * A variation on {@code ChoiceCallback} which supports the extended callback interface.
+ *
+ * @author David M. Lloyd
+ */
+public class ExtendedChoiceCallback extends ChoiceCallback implements ExtendedCallback {
+
+ private static final long serialVersionUID = 2222777746412093737L;
+
+ /**
+ * @serial A flag indicating whether the callback is optional.
+ */
+ private final boolean optional;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the text prompt (must not be {@code null})
+ * @param choices the choices (must not be {@code null})
+ * @param defaultChoice the default choice as an index into the {@code choices} array
+ * @param multipleSelectionsAllowed {@code true} if multiple selections are allowed
+ * @param optional {@code true} if the support for the callback is optional
+ */
+ public ExtendedChoiceCallback(final String prompt, final String[] choices, final int defaultChoice, final boolean multipleSelectionsAllowed, final boolean optional) {
+ super(prompt, choices, defaultChoice, multipleSelectionsAllowed);
+ this.optional = optional;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/FastUnsupportedCallbackException.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/FastUnsupportedCallbackException.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/FastUnsupportedCallbackException.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * A version of {@code UnsupportedCallbackException} which does not initialize a full stack trace, and thus is much
+ * more efficient to construct.
+ *
+ * @author David M. Lloyd
+ */
+public class FastUnsupportedCallbackException extends UnsupportedCallbackException {
+
+ private static final long serialVersionUID = -990072831042809709L;
+
+ private static final StackTraceElement[] NO_STACK = new StackTraceElement[0];
+
+ /**
+ * Constructs a new {@code FastUnsupportedCallbackException} instance. The message is left blank ({@code null}),
+ * and no cause is specified.
+ *
+ * @param callback the callback which is not supported (should not be {@code null})
+ */
+ public FastUnsupportedCallbackException(final Callback callback) {
+ super(callback);
+ }
+
+ /**
+ * Constructs a new {@code FastUnsupportedCallbackException} instance with an initial message. No cause is
+ * specified.
+ *
+ * @param callback the callback which is not supported (should not be {@code null})
+ * @param msg the message
+ */
+ public FastUnsupportedCallbackException(final Callback callback, final String msg) {
+ super(callback, msg);
+ }
+
+ /**
+ * Does nothing but return this instance.
+ *
+ * @param cause ignored
+ * @return this instance
+ */
+ public Throwable initCause(final Throwable cause) {
+ return this;
+ }
+
+ /**
+ * Returns an empty stack.
+ *
+ * @return an empty stack
+ */
+ public StackTraceElement[] getStackTrace() {
+ return NO_STACK;
+ }
+
+ /**
+ * Does nothing but return this instance.
+ *
+ * @return this instance
+ */
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+
+ /**
+ * Does nothing.
+ *
+ * @param stackTrace ignored
+ */
+ public void setStackTrace(final StackTraceElement[] stackTrace) {
+ }
+
+ /**
+ * Get the message for this exception, formatted with the callback.
+ *
+ * @return the message for this exception, with the callback (not {@code null})
+ */
+ public String getMessage() {
+ final String message = super.getMessage();
+ return message != null ? String.format("%s: %s", getCallback(), message) : String.valueOf(getCallback());
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/IdentityCredentialCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/IdentityCredentialCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/IdentityCredentialCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.security.credential.Credential;
+
+/**
+ * A callback to inform a server authentication mechanism of a credential which may be cached on the authentication
+ * identity (if any). The credential may be public or private.
+ *
+ * @author David M. Lloyd
+ */
+public final class IdentityCredentialCallback implements ExtendedCallback {
+ private final Credential credential;
+ private final boolean isPrivate;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param credential the credential (must not be {@code null})
+ * @param isPrivate {@code true} if the credential should be private, {@code false} if it can be public
+ */
+ public IdentityCredentialCallback(final Credential credential, final boolean isPrivate) {
+ this.credential = credential;
+ this.isPrivate = isPrivate;
+ }
+
+ /**
+ * Get the credential.
+ *
+ * @return the credential (not {@code null})
+ */
+ public Credential getCredential() {
+ return credential;
+ }
+
+ /**
+ * Determine whether the credential should be treated as private.
+ *
+ * @return {@code true} to treat the credential as private, {@code false} otherwise
+ */
+ public boolean isPrivate() {
+ return isPrivate;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/MechanismInformationCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/MechanismInformationCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/MechanismInformationCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+
+import org.wildfly.security.auth.server.MechanismInformation;
+
+/**
+ * A {@link Callback} to pass the information about the current mechanism to the {@link CallbackHandler}.
+ *
+ * As an informational {@code Callback} it is optional for the {@code CallbackHandler} to handle this.
+ *
+ * @author Darran Lofthouse
+ */
+public class MechanismInformationCallback implements ExtendedCallback {
+
+ private final MechanismInformation mechanismInformation;
+
+ /**
+ * Construct a new instance with the appropriate mechanism information.
+ *
+ * @param mechanismInformation the mechanism information for the current authentication attempt.
+ */
+ public MechanismInformationCallback(final MechanismInformation mechanismInformation) {
+ this.mechanismInformation = mechanismInformation;
+ }
+
+ /**
+ * Get the type of the mechanism information for the current authentication attempt.
+ *
+ * @return the type of the mechanism for the current authentication.
+ */
+ public MechanismInformation getMechanismInformation() {
+ return mechanismInformation;
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/OptionalNameCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/OptionalNameCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/OptionalNameCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2017 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.NameCallback;
+
+/**
+ * A {@code NameCallback} which is optional, for mechanisms that can accept a name from the server.
+ *
+ * @author David M. Lloyd
+ */
+public final class OptionalNameCallback extends NameCallback implements ExtendedCallback {
+ private static final long serialVersionUID = 1848637046120873969L;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the prompt to offer the user
+ */
+ public OptionalNameCallback(final String prompt) {
+ super(prompt);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the prompt to offer the user
+ * @param defaultName the default name to specify (must not be {@code null})
+ */
+ public OptionalNameCallback(final String prompt, final String defaultName) {
+ super(prompt, defaultName);
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ParameterCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ParameterCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ParameterCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import static org.wildfly.security.auth.server._private.ElytronMessages.log;
+
+import java.io.Serializable;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * A callback used to acquire parameter specifications, either for outbound or inbound authentication. The supplied parameter
+ * information may be used to select an authentication mechanism, or to set parameters for an establishing mechanism.
+ * The supplied parameter specification should be of a supported
+ * type; the {@link #isParameterSupported(AlgorithmParameterSpec)} and {@link #isParameterTypeSupported(Class)} methods can be
+ * used to query the types that are supported. If no credential is available, {@code null} is set, and
+ * authentication may fail. If an unsupported credential type is set, authentication may fail.
+ *
+ * @author David M. Lloyd
+ */
+public final class ParameterCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = -6000106115779144082L;
+
+ /**
+ * @serial The list of allowed parameter specification types.
+ */
+ private final Class extends AlgorithmParameterSpec>[] allowedTypes;
+ /**
+ * @serial The algorithm parameter specification.
+ */
+ private AlgorithmParameterSpec parameterSpec;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param allowedTypes the allowed types of parameter specification
+ */
+ @SafeVarargs
+ public ParameterCallback(final Class extends AlgorithmParameterSpec>... allowedTypes) {
+ this.allowedTypes = allowedTypes;
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param parameterSpec the default parameter spec value, if any
+ * @param allowedTypes the allowed types of parameter spec
+ */
+ @SafeVarargs
+ public ParameterCallback(final AlgorithmParameterSpec parameterSpec, final Class extends AlgorithmParameterSpec>... allowedTypes) {
+ this.allowedTypes = allowedTypes;
+ this.parameterSpec = parameterSpec;
+ }
+
+ /**
+ * Get the parameter specification.
+ *
+ * @return the parameter specification, or {@code null} if it wasn't set yet
+ */
+ public AlgorithmParameterSpec getParameterSpec() {
+ return parameterSpec;
+ }
+
+ /**
+ * Set the parameter specification.
+ *
+ * @param parameterSpec the parameter specification, or {@code null} if no parameter specification is available
+ */
+ public void setParameterSpec(final AlgorithmParameterSpec parameterSpec) {
+ if (! isParameterSupported(parameterSpec)) {
+ throw log.invalidCredentialTypeSpecified();
+ }
+ this.parameterSpec = parameterSpec;
+ }
+
+ /**
+ * Determine whether a parameter specification would be supported by the authentication.
+ *
+ * @param parameterSpec the parameter specification to test
+ * @return {@code true} if the parameter specification is non-{@code null} and supported, {@code false} otherwise
+ */
+ public boolean isParameterSupported(final AlgorithmParameterSpec parameterSpec) {
+ for (final Class> allowedType : allowedTypes) {
+ if (allowedType.isInstance(parameterSpec)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Determine whether a credential type would be supported by the authentication.
+ *
+ * @param parameterType the parameter specification type to test
+ * @return {@code true} if the parameter specification type is supported, {@code false} otherwise
+ */
+ public boolean isParameterTypeSupported(final Class extends AlgorithmParameterSpec> parameterType) {
+ for (final Class extends AlgorithmParameterSpec> allowedType : allowedTypes) {
+ if (allowedType.isAssignableFrom(parameterType)) return true;
+ }
+ return false;
+ }
+
+ public boolean isOptional() {
+ return parameterSpec != null;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PasswordResetCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PasswordResetCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PasswordResetCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2017 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.wildfly.common.Assert;
+
+/**
+ * A callback used when a password reset is required. Interactive callback handlers should have the user enter the
+ * password two times, comparing them for equality.
+ *
+ * @author David M. Lloyd
+ */
+public final class PasswordResetCallback implements ExtendedCallback, Serializable{
+ private static final long serialVersionUID = - 8789058459408593766L;
+
+ private final String prompt;
+
+ private char[] password;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param prompt the password reset prompt (must not be {@code null} or empty)
+ */
+ public PasswordResetCallback(final String prompt) {
+ Assert.checkNotNullParam("prompt", prompt);
+ Assert.checkNotEmptyParam("prompt", prompt);
+ this.prompt = prompt;
+ }
+
+ /**
+ * Get the password reset prompt.
+ *
+ * @return the password reset prompt
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Get the new password.
+ *
+ * @return the new password, or {@code null} if it was not set
+ */
+ public char[] getPassword() {
+ final char[] password = this.password;
+ return password == null ? null : password.clone();
+ }
+
+ /**
+ * Set the new password.
+ *
+ * @param password the new password
+ */
+ public void setPassword(final char[] password) {
+ this.password = password == null ? null : password.clone();
+ }
+
+ /**
+ * Clear the stored password bytes by setting them to {@code ' '}.
+ */
+ public void clearPassword() {
+ final char[] password = this.password;
+ if (password != null) {
+ Arrays.fill(password, ' ');
+ }
+ }
+
+ public boolean isOptional() {
+ return false;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PeerPrincipalCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PeerPrincipalCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PeerPrincipalCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.common.Assert;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * An optional callback to inform the callback handler of the peer's principal identity.
+ *
+ * @author David M. Lloyd
+ */
+public final class PeerPrincipalCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = -2876104318406026491L;
+
+ /**
+ * @serial The peer principal.
+ */
+ private final Principal principal;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param principal the peer principal
+ */
+ public PeerPrincipalCallback(final Principal principal) {
+ Assert.checkNotNullParam("principal", principal);
+ this.principal = principal;
+ }
+
+ /**
+ * Get the peer principal.
+ *
+ * @return the peer principal
+ */
+ public Principal getPrincipal() {
+ return principal;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PrincipalAuthorizeCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PrincipalAuthorizeCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/PrincipalAuthorizeCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.security.Principal;
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.principal.NamePrincipal;
+
+/**
+ * An authorization callback similar to javase {@link javax.security.sasl.AuthorizeCallback}
+ * but using a generic principal.
+ *
+ * @author rmartinc
+ */
+public class PrincipalAuthorizeCallback implements ExtendedCallback {
+
+ private final Principal principal;
+ private boolean authorized;
+
+ /**
+ * Creates a new instance to authorize the associated name
.
+ * It will be transformed in a {@link NamePrincipal}.
+ *
+ * @param name the name to authorize
+ */
+ public PrincipalAuthorizeCallback(String name) {
+ Assert.checkNotNullParam("name", name);
+ this.principal = new NamePrincipal(name);
+ }
+
+ /**
+ * Creates a new instance to authorize the associated principal
.
+ *
+ * @param principal the principal to authorize
+ */
+ public PrincipalAuthorizeCallback(Principal principal) {
+ Assert.checkNotNullParam("principal", principal);
+ this.principal = principal;
+ }
+
+ /**
+ * Indicates if the principal was successfully authorized.
+ *
+ * @return true if the principal was successfully authorized. Otherwise, false
+ */
+ public boolean isAuthorized() {
+ return authorized;
+ }
+
+ /**
+ * Sets whether the authorization is allowed for the principal.
+ *
+ * @param authorized authorization result
+ */
+ public void setAuthorized(boolean authorized) {
+ this.authorized = authorized;
+ }
+
+ /**
+ * Returns the {@link Principal}.
+ *
+ * @return the principal (not {@code null})
+ */
+ public Principal getPrincipal() {
+ return this.principal;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/RequestInformationCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/RequestInformationCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/RequestInformationCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2023 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.callback;
+
+import javax.security.auth.callback.Callback;
+import java.util.HashMap;
+
+import static org.wildfly.common.Assert.checkNotNullParam;
+
+/**
+ * A {@link javax.security.auth.callback.Callback} to inform a server authentication context about current authentication request.
+ *
+ */
+public class RequestInformationCallback implements ExtendedCallback {
+
+ /**
+ * Properties of the current authentication request
+ */
+ private final HashMap props;
+
+ /**
+ * Construct a new instance of this {@link Callback}.
+ *
+ * @param props Properties of the current authentication request
+ */
+ public RequestInformationCallback(HashMap props) {
+ checkNotNullParam("props", props);
+ this.props = props;
+ }
+
+ /**
+ * Get the properties of this request.
+ *
+ * @return properties of the current authentication request
+ */
+ public HashMap getProperties() {
+ return this.props;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SSLCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SSLCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SSLCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import static org.wildfly.common.Assert.checkNotNullParam;
+
+import javax.net.ssl.SSLSession;
+
+import org.wildfly.security.ssl.SSLConnection;
+
+/**
+ * A callback which provides information to the callback handler about the established SSLSession.
+ *
+ * @author David M. Lloyd
+ */
+public final class SSLCallback implements ExtendedCallback {
+
+ /**
+ * @serial The SSL session.
+ */
+ private final SSLConnection sslConnection;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param sslConnection the SSL connection (must not be {@code null})
+ */
+ public SSLCallback(final SSLConnection sslConnection) {
+ checkNotNullParam("sslConnection", sslConnection);
+ this.sslConnection = sslConnection;
+ }
+
+ /**
+ * Get the SSL session in force.
+ *
+ * @return the SSL session in force
+ */
+ public SSLSession getSslSession() {
+ return sslConnection.getSession();
+ }
+
+ /**
+ * Get the SSL connection.
+ *
+ * @return the SSL connection
+ */
+ public SSLConnection getSslConnection() {
+ return sslConnection;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityIdentityCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityIdentityCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityIdentityCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.security.auth.server.SecurityIdentity;
+
+/**
+ * A server-side callback used to pass a realm identity from the callback handler to the authentication mechanism. If
+ * no realm identity is returned, any inflowed security context will be treated as anonymous.
+ *
+ * @author David M. Lloyd
+ */
+public final class SecurityIdentityCallback implements ExtendedCallback {
+
+ private SecurityIdentity securityIdentity;
+
+ /**
+ * Construct a new instance.
+ */
+ public SecurityIdentityCallback() {
+ }
+
+ /**
+ * Get the realm identity.
+ *
+ * @return the realm identity, or {@code null} if there is none
+ */
+ public SecurityIdentity getSecurityIdentity() {
+ return securityIdentity;
+ }
+
+ /**
+ * Set the realm identity.
+ *
+ * @param securityIdentity the realm identity, or {@code null} if there is none
+ */
+ public void setSecurityIdentity(final SecurityIdentity securityIdentity) {
+ this.securityIdentity = securityIdentity;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityLayerDisposedCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityLayerDisposedCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SecurityLayerDisposedCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.Serializable;
+
+/**
+ * A callback which indicates that the corresponding security layer (SASL client, SASL server, etc.) has been disposed
+ * and any related resources may be relinquished.
+ *
+ * @author David M. Lloyd
+ */
+public final class SecurityLayerDisposedCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = 3720690487735346163L;
+
+ private static final SecurityLayerDisposedCallback INSTANCE = new SecurityLayerDisposedCallback();
+
+ private SecurityLayerDisposedCallback() {
+ }
+
+ /**
+ * Get the singleton instance.
+ *
+ * @return the singleton instance
+ */
+ public static SecurityLayerDisposedCallback getInstance() {
+ return INSTANCE;
+ }
+
+ Object readResolve() {
+ return INSTANCE;
+ }
+
+ Object writeReplace() {
+ return INSTANCE;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ServerCredentialCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ServerCredentialCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/ServerCredentialCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.wildfly.security.credential.Credential;
+
+/**
+ * A callback used to acquire the server (or "host") credential. This callback is only used on the server side of
+ * authentication mechanisms; client callback handlers do not need to recognize this callback. The callback handler is
+ * expected to provide a credential to this callback. If no credential is available, {@code null} is set, and
+ * authentication may fail. If an unsupported credential type is set, an exception is thrown.
+ *
+ * @author David M. Lloyd
+ */
+public final class ServerCredentialCallback extends AbstractCredentialCallback {
+
+ /**
+ * Construct a new instance.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ * @param algorithm the algorithm name, or {@code null} if any algorithm is suitable or the credential
+ * type does not use algorithm names
+ * @param parameterSpec the parameters to use or {@code null} for no parameters
+ */
+ public ServerCredentialCallback(final Class extends Credential> credentialType, final String algorithm, final AlgorithmParameterSpec parameterSpec) {
+ super(credentialType, algorithm, parameterSpec);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ * @param algorithm the algorithm name, or {@code null} if any algorithm is suitable or the credential
+ * type does not use algorithm names
+ */
+ public ServerCredentialCallback(final Class extends Credential> credentialType, final String algorithm) {
+ this(credentialType, algorithm, null);
+ }
+
+ /**
+ * Construct a new instance which accepts any algorithm name.
+ *
+ * @param credentialType the desired credential type (must not be {@code null})
+ */
+ public ServerCredentialCallback(final Class extends Credential> credentialType) {
+ this(credentialType, null, null);
+ }
+
+ public boolean isOptional() {
+ return false;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,97 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import org.wildfly.common.Assert;
+
+import java.io.Serializable;
+import java.net.SocketAddress;
+
+/**
+ * An optional callback which is used to inform the callback handler of the endpoint addresses of a connection being
+ * authenticated.
+ *
+ * @author David M. Lloyd
+ */
+public final class SocketAddressCallback implements ExtendedCallback, Serializable {
+
+ private static final long serialVersionUID = -4287450716990929230L;
+
+ /**
+ * @serial The socket address.
+ */
+ private final SocketAddress address;
+ /**
+ * @serial The socket address disposition or "kind".
+ */
+ private final Kind kind;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param address the endpoint socket address
+ * @param kind the disposition of the endpoint
+ */
+ public SocketAddressCallback(final SocketAddress address, final Kind kind) {
+ this.address = Assert.checkNotNullParam("address", address);
+ this.kind = Assert.checkNotNullParam("kind", kind);
+ }
+
+ /**
+ * Construct a new instance. The disposition is assumed to be {@link Kind#PEER}.
+ *
+ * @param address the endpoint socket address
+ */
+ public SocketAddressCallback(final SocketAddress address) {
+ this(address, Kind.PEER);
+ }
+
+ /**
+ * Get the endpoint socket address.
+ *
+ * @return the endpoint socket address
+ */
+ public SocketAddress getAddress() {
+ return address;
+ }
+
+ /**
+ * Get the endpoint disposition.
+ *
+ * @return the endpoint disposition
+ */
+ public Kind getKind() {
+ return kind;
+ }
+
+ /**
+ * Endpoint disposition kinds.
+ */
+ public enum Kind {
+ /**
+ * The local endpoint.
+ */
+ LOCAL,
+ /**
+ * The remote (peer) endpoint.
+ */
+ PEER,
+ ;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressQueryCallbackHandler.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressQueryCallbackHandler.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/SocketAddressQueryCallbackHandler.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * A callback handler which delegates to another callback handler, passing the local and/or peer socket address to that
+ * callback handler on its first invocation.
+ *
+ * @author David M. Lloyd
+ */
+public final class SocketAddressQueryCallbackHandler implements CallbackHandler {
+ private final CallbackHandler delegate;
+ private final SocketAddress localAddress;
+ private final SocketAddress peerAddress;
+
+ private final AtomicBoolean once = new AtomicBoolean();
+
+ /**
+ * Construct a new instance.
+ *
+ * @param delegate the callback handler to delegate to
+ * @param localAddress the local socket address
+ * @param peerAddress the peer socket address
+ */
+ public SocketAddressQueryCallbackHandler(final CallbackHandler delegate, final SocketAddress localAddress, final SocketAddress peerAddress) {
+ this.delegate = delegate;
+ this.localAddress = localAddress;
+ this.peerAddress = peerAddress;
+ }
+
+ public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ if (localAddress == null && peerAddress == null || ! once.compareAndSet(false, true)) {
+ delegate.handle(callbacks);
+ return;
+ }
+ final SocketAddressCallback localCallback = localAddress == null ? null : new SocketAddressCallback(localAddress, SocketAddressCallback.Kind.LOCAL);
+ final SocketAddressCallback peerCallback = peerAddress == null ? null : new SocketAddressCallback(peerAddress, SocketAddressCallback.Kind.PEER);
+ final Callback[] newCallbacks;
+ final int length = callbacks.length;
+ if (localCallback != null && peerCallback != null) {
+ newCallbacks = new Callback[length + 2];
+ newCallbacks[0] = localCallback;
+ newCallbacks[1] = peerCallback;
+ System.arraycopy(callbacks, 0, newCallbacks, 2, length);
+ } else if (localCallback != null) {
+ newCallbacks = new Callback[length + 1];
+ newCallbacks[0] = localCallback;
+ System.arraycopy(callbacks, 0, newCallbacks, 1, length);
+ } else {
+ // peerCallback != null
+ newCallbacks = new Callback[length + 1];
+ newCallbacks[0] = peerCallback;
+ System.arraycopy(callbacks, 0, newCallbacks, 1, length);
+ }
+ try {
+ delegate.handle(newCallbacks);
+ } catch (UnsupportedCallbackException e) {
+ if (e.getCallback() instanceof SocketAddressCallback) {
+ delegate.handle(callbacks);
+ return;
+ }
+ throw e;
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/TrustedAuthoritiesCallback.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/TrustedAuthoritiesCallback.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/TrustedAuthoritiesCallback.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.callback;
+
+import java.util.List;
+
+import org.wildfly.security.x500.TrustedAuthority;
+
+/**
+ * An optional callback used to retrieve information about trusted certificate authorities
+ * for authenticating peers.
+ *
+ * @author Farah Juma
+ */
+public final class TrustedAuthoritiesCallback implements ExtendedCallback {
+
+ private List trustedAuthorities;
+
+ /**
+ * Construct a new instance.
+ */
+ public TrustedAuthoritiesCallback() {
+ }
+
+ /**
+ * Get the retrieved trusted authorities.
+ *
+ * @return the retrieved trusted authorities (may be {@code null})
+ */
+ public List getTrustedAuthorities() {
+ return trustedAuthorities;
+ }
+
+ /**
+ * Set the retrieved trusted authorities.
+ *
+ * @param trustedAuthorities the retrieved trusted authorities (may be {@code null})
+ */
+ public void setTrustedAuthorities(final List trustedAuthorities) {
+ this.trustedAuthorities = trustedAuthorities;
+ }
+
+ public boolean needsInformation() {
+ return true;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/callback/package-info.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/callback/package-info.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/callback/package-info.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,22 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Extended callbacks and supporting utilities which allow efficient callback handler implementation.
+ */
+package org.wildfly.security.auth.callback;
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/package-info.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/package-info.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/package-info.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,22 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Classes relating to authentication on the client and server side.
+ */
+package org.wildfly.security.auth;
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/permission/ChangeRoleMapperPermission.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/permission/ChangeRoleMapperPermission.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/permission/ChangeRoleMapperPermission.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.permission;
+
+import org.wildfly.security.permission.AbstractNameOnlyPermission;
+
+/**
+ * The permission to change a role mapper category on a security identity.
+ */
+public final class ChangeRoleMapperPermission extends AbstractNameOnlyPermission {
+
+ private static final long serialVersionUID = - 6742662884954321082L;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name the category name, or {@code *} for all categories
+ */
+ public ChangeRoleMapperPermission(final String name) {
+ super(name);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name the category name, or {@code *} for all categories
+ * @param ignored the permission actions (ignored)
+ */
+ public ChangeRoleMapperPermission(final String name, @SuppressWarnings("unused") final String ignored) {
+ this(name);
+ }
+
+ public ChangeRoleMapperPermission withName(final String name) {
+ return new ChangeRoleMapperPermission(name);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/permission/LoginPermission.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/permission/LoginPermission.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/permission/LoginPermission.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.permission;
+
+import org.wildfly.security.permission.AbstractBooleanPermission;
+
+/**
+ * Establish whether the current identity has permission to complete an authentication ("log in").
+ *
+ * @author David M. Lloyd
+ */
+public final class LoginPermission extends AbstractBooleanPermission {
+
+ private static final long serialVersionUID = - 5776174571770792690L;
+
+ /**
+ * Construct a new instance.
+ */
+ public LoginPermission() {
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name ignored
+ */
+ public LoginPermission(@SuppressWarnings("unused") final String name) {
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name ignored
+ * @param actions ignored
+ */
+ public LoginPermission(@SuppressWarnings("unused") final String name, @SuppressWarnings("unused") final String actions) {
+ }
+
+ private static final LoginPermission INSTANCE = new LoginPermission();
+
+ /**
+ * Get the instance of this class.
+ *
+ * @return the instance of this class
+ */
+ public static LoginPermission getInstance() {
+ return INSTANCE;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/permission/RunAsPrincipalPermission.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/permission/RunAsPrincipalPermission.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/permission/RunAsPrincipalPermission.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.permission;
+
+import org.wildfly.security.permission.AbstractNameOnlyPermission;
+
+/**
+ * The permission to run as another principal within some security domain. Note that this permission is checked relative
+ * to the security domain that the user is authenticated to. The principal name is the effective name after all rewrite
+ * operations have taken place.
+ */
+public final class RunAsPrincipalPermission extends AbstractNameOnlyPermission {
+
+ private static final long serialVersionUID = -3361334389433669815L;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name the principal name, or {@code *} for global run-as permissions
+ */
+ public RunAsPrincipalPermission(final String name) {
+ super(name);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name the principal name, or {@code *} for global run-as permissions
+ * @param ignored the permission actions (ignored)
+ */
+ public RunAsPrincipalPermission(final String name, @SuppressWarnings("unused") final String ignored) {
+ this(name);
+ }
+
+ public RunAsPrincipalPermission withName(final String name) {
+ return new RunAsPrincipalPermission(name);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/permission/package-info.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/permission/package-info.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/permission/package-info.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,22 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Permissions which pertain to authentication and authorization.
+ */
+package org.wildfly.security.auth.permission;
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/AnonymousPrincipal.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/AnonymousPrincipal.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/AnonymousPrincipal.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,100 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.principal;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * The singleton anonymous principal.
+ */
+public final class AnonymousPrincipal implements Principal, Serializable {
+
+ private static final long serialVersionUID = -2539713938519809712L;
+
+ private static final AnonymousPrincipal INSTANCE = new AnonymousPrincipal();
+
+ /**
+ * Construct a new instance (should not be used; call {@link #getInstance()} instead).
+ */
+ public AnonymousPrincipal() {
+ }
+
+ /**
+ * Construct a new instance (should not be used; call {@link #getInstance()} instead).
+ *
+ * @param ignored ignored
+ */
+ public AnonymousPrincipal(String ignored) {
+ }
+
+ /**
+ * Get the anonymous principal instance.
+ *
+ * @return the anonymous principal instance
+ */
+ public static AnonymousPrincipal getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Get the principal name (always "anonymous").
+ *
+ * @return the principal name (always "anonymous")
+ */
+ public String getName() {
+ return "anonymous";
+ }
+
+ /**
+ * Determine whether the given object is also an anonymous principal.
+ *
+ * @param o the other object
+ * @return {@code true} if the object is an anonymous principal, {@code false} otherwise
+ */
+ public boolean equals(final Object o) {
+ return o instanceof AnonymousPrincipal;
+ }
+
+ /**
+ * Get the hash code of this principal.
+ *
+ * @return the hash code of this principal
+ */
+ public int hashCode() {
+ return 3;
+ }
+
+ /**
+ * Get a representation of the principal name (always "anonymous").
+ *
+ * @return the string representation of the principal name (always "anonymous")
+ */
+ public String toString() {
+ return "anonymous";
+ }
+
+ Object writeReplace() {
+ return INSTANCE;
+ }
+
+ Object readResolve() {
+ return INSTANCE;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/CompositePrincipal.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/CompositePrincipal.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/CompositePrincipal.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,225 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.principal;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.util.ArrayIterator;
+
+/**
+ * A composite principal that consists of multiple elements of possibly disparate type. This may be used to locate
+ * a unique principal in a realm which is backed by a database that uses a composite key; in this case, the constituent
+ * principals may be names or numbers, or a combination of both.
+ *
+ * @author David M. Lloyd
+ */
+public final class CompositePrincipal implements Principal, Serializable, Iterable {
+ private static final long serialVersionUID = - 2610733957848661774L;
+ private static final Principal[] NO_PRINCIPALS = new Principal[0];
+
+ private final Principal[] p;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param principals the collection of principals to use (must not be {@code null})
+ */
+ public CompositePrincipal(Collection principals) {
+ this(principals.toArray(NO_PRINCIPALS), false);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param principals the principals to use (must not be {@code null})
+ */
+ public CompositePrincipal(Principal... principals) {
+ this(principals, true);
+ }
+
+ private CompositePrincipal(Principal[] principals, boolean clone) {
+ p = principals.length == 0 ? NO_PRINCIPALS : clone ? principals.clone() : principals;
+ for (int i = 0; i < p.length; i++) {
+ Assert.checkNotNullArrayParam("principals", i, p[i]);
+ }
+ }
+
+ /**
+ * Get the principal name.
+ *
+ * @return the principal name, which is a string containing all of the nested principals
+ */
+ public String getName() {
+ return Arrays.toString(p);
+ }
+
+ /**
+ * Determine whether this composite principal contains the given nested principal.
+ *
+ * @param principal the nested principal (must not be {@code null})
+ * @return {@code true} if this principal contains the nested principal, {@code false} otherwise
+ */
+ public boolean contains(final Principal principal) {
+ Assert.checkNotNullParam("principal", principal);
+ for (Principal test : p) {
+ if (test.equals(principal)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine whether this composite principal contains the a nested principal of the given type class.
+ *
+ * @param type the nested principal type class (must not be {@code null})
+ * @return {@code true} if this principal contains a nested principal of the given type, {@code false} otherwise
+ */
+ public boolean contains(final Class extends Principal> type) {
+ Assert.checkNotNullParam("type", type);
+ for (Principal test : p) {
+ if (type.isInstance(test)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the number of nested principals.
+ *
+ * @return the number of nested principals
+ */
+ public int size() {
+ return p.length;
+ }
+
+ /**
+ * Get the principal at the given index.
+ *
+ * @param idx the index
+ * @return the principal at the given index (not {@code null})
+ * @throws IndexOutOfBoundsException if the given index is less than zero or greater than or equal to {@link #size()}
+ */
+ public Principal get(int idx) {
+ try {
+ return p[idx];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+ /**
+ * Get the principal at the given index, if it is of the given type.
+ *
+ * @param idx the index
+ * @param type the principal type class (must not be {@code null})
+ * @param the principal type
+ * @return the principal at the given index or {@code null} if that principal is not of the given type
+ * @throws IndexOutOfBoundsException if the given index is less than zero or greater than or equal to {@link #size()}
+ */
+ public
P get(int idx, Class
type) {
+ Assert.checkNotNullParam("type", type);
+ final Principal item = get(idx);
+ return type.isInstance(item) ? type.cast(item) : null;
+ }
+
+ /**
+ * Get the first principal with the given type, if any.
+ *
+ * @param type the principal type class (must not be {@code null})
+ * @param
the principal type
+ * @return the first principal with the given type, or {@code null} if none was found
+ * @throws IndexOutOfBoundsException if the given index is less than zero or greater than or equal to {@link #size()}
+ */
+ public
P get(Class
type) {
+ Assert.checkNotNullParam("type", type);
+ for (Principal item : p) {
+ if (type.isInstance(item)) type.cast(item);
+ }
+ return null;
+ }
+
+ /**
+ * Get an iterator over this principal.
+ *
+ * @return an iterator over this principal (not {@code null})
+ */
+ public Iterator iterator() {
+ return new ArrayIterator(p);
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final Object obj) {
+ return obj instanceof CompositePrincipal && equals((CompositePrincipal) obj);
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final CompositePrincipal obj) {
+ return obj == this || obj != null && Arrays.deepEquals(p, obj.p);
+ }
+
+ /**
+ * Get the hash code of this principal.
+ *
+ * @return the hash code of this principal
+ */
+ public int hashCode() {
+ return Arrays.deepHashCode(p);
+ }
+
+ /**
+ * Get this principal as a string.
+ *
+ * @return this principal as a string (not {@code null})
+ */
+ public String toString() {
+ return getName();
+ }
+
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ if (p == null) {
+ throw new InvalidObjectException("Null principals array");
+ }
+ for (Principal principal : p) {
+ if (principal == null) {
+ throw new InvalidObjectException("Null principal array element");
+ }
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NamePrincipal.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NamePrincipal.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NamePrincipal.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.principal;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.wildfly.common.Assert;
+
+/**
+ * A principal which is comprised of a simple {@code String} name.
+ *
+ * @author David M. Lloyd
+ */
+public final class NamePrincipal implements Principal, Serializable {
+
+ private static final long serialVersionUID = -6380283371738985125L;
+
+ /**
+ * @serial The principal name.
+ */
+ private final String name;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param name the principal name
+ */
+ public NamePrincipal(final String name) {
+ Assert.checkNotNullParam("name", name);
+ this.name = name;
+ }
+
+ /**
+ * Get the principal name.
+ *
+ * @return the principal name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the hash code of this principal.
+ *
+ * @return the hash code of this principal
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final Object obj) {
+ return obj instanceof NamePrincipal && equals((NamePrincipal) obj);
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final NamePrincipal obj) {
+ return obj != null && name.equals(obj.name);
+ }
+
+ /**
+ * Get a string representation of this principal.
+ *
+ * @return the string representation of this principal
+ */
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Attempt to convert the given principal to a {@code NamePrincipal}.
+ *
+ * @param principal the original principal
+ * @return the {@code NamePrincipal} or {@code null} if the principal cannot be converted
+ */
+ public static NamePrincipal from(Principal principal) {
+ if (principal instanceof NamePrincipal) {
+ return (NamePrincipal) principal;
+ }
+ return isConvertibleTo(principal) ? new NamePrincipal(principal.getName()) : null;
+ }
+
+ /**
+ * Check if the given principal could be converted to a {@code NamePrincipal}.
+ *
+ * @param principal the original principal
+ * @return {@code true} if the principal can be converted to a {@code NamePrincipal} and {@code false} otherwise
+ */
+ public static boolean isConvertibleTo(Principal principal) {
+ if (principal instanceof NamePrincipal) {
+ return true;
+ }
+ if (principal != null) {
+ String name = principal.getName();
+ if (name != null && ! name.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NumericPrincipal.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NumericPrincipal.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/NumericPrincipal.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,111 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.principal;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * A principal which is represented by a numeric ID, such as what a database might use for a primary key.
+ *
+ * @author David M. Lloyd
+ */
+public final class NumericPrincipal implements Principal, Serializable {
+ private static final long serialVersionUID = 6679865697029801196L;
+
+ /**
+ * @serial the principal ID
+ */
+ private final long id;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param id the ID of the principal
+ */
+ public NumericPrincipal(final long id) {
+ this.id = id;
+ }
+
+ /**
+ * Construct a new instance from a decimal string.
+ *
+ * @param id the ID of the principal, as a string
+ * @throws NumberFormatException if the number is not a valid non-negative long integer
+ */
+ public NumericPrincipal(final String id) throws NumberFormatException {
+ this(Long.parseUnsignedLong(id));
+ }
+
+ /**
+ * Get the ID of the principal.
+ *
+ * @return the ID of the principal
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final Object obj) {
+ return obj instanceof NumericPrincipal && equals((NumericPrincipal) obj);
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final NumericPrincipal obj) {
+ return obj != null && id == obj.id;
+ }
+
+ /**
+ * Get the hash code of this principal.
+ *
+ * @return the hash code of this principal
+ */
+ public int hashCode() {
+ return (int) id;
+ }
+
+ /**
+ * Get this principal as a string.
+ *
+ * @return this principal as a string (not {@code null})
+ */
+ public String toString() {
+ return getName();
+ }
+
+ /**
+ * Returns the name of this principal, which is just the string representation of the ID.
+ *
+ * @return the name of this principal (not {@code null})
+ */
+ public String getName() {
+ return Long.toUnsignedString(id);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/RealmNestedPrincipal.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/RealmNestedPrincipal.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/RealmNestedPrincipal.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.principal;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.wildfly.common.Assert;
+
+/**
+ * A principal type which is used to find a specific identity in a specific realm. This principal can be used to locate
+ * an exact identity whose name may have changed or may be unknown, but which can be located another way (for example,
+ * by primary key).
+ *
+ * @author David M. Lloyd
+ */
+public final class RealmNestedPrincipal implements Principal, Serializable {
+ private static final long serialVersionUID = 3776427564561628331L;
+
+ // names are short to facilitate serialization
+ /**
+ * @serial the realm name (must not be {@code null})
+ */
+ private final String r;
+ /**
+ * @serial the nested principal (must not be {@code null})
+ */
+ private final Principal p;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param realmName the realm name (must not be {@code null})
+ * @param nestedPrincipal the nested principal (must not be {@code null})
+ */
+ public RealmNestedPrincipal(final String realmName, final Principal nestedPrincipal) {
+ Assert.checkNotNullParam("realmName", realmName);
+ Assert.checkNotNullParam("nestedPrincipal", nestedPrincipal);
+ this.r = realmName;
+ this.p = nestedPrincipal;
+ }
+
+ /**
+ * Get the realm name.
+ *
+ * @return the realm name (not {@code null})
+ */
+ public String getRealmName() {
+ return r;
+ }
+
+ /**
+ * Get the nested principal.
+ *
+ * @return the nested principal (not {@code null})
+ */
+ public Principal getNestedPrincipal() {
+ return p;
+ }
+
+ /**
+ * Get the nested principal if it is of the given type class.
+ *
+ * @return the nested principal, or {@code null} if the nested principal is not of the given type
+ */
+ public P getNestedPrincipal(Class
principalClass) {
+ return principalClass.isInstance(p) ? principalClass.cast(p) : null;
+ }
+
+ /**
+ * Returns the name of this principal, which is composed of the realm name and the name of the nested principal.
+ *
+ * @return the name of this principal
+ */
+ public String getName() {
+ return r + "/" + p.getName();
+ }
+
+ /**
+ * Get the hash code of this principal.
+ *
+ * @return the hash code of this principal
+ */
+ public int hashCode() {
+ return r.hashCode() * 17 + p.hashCode();
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final Object obj) {
+ return obj instanceof RealmNestedPrincipal && equals((RealmNestedPrincipal) obj);
+ }
+
+ /**
+ * Determine whether this principal is equal to the given object.
+ *
+ * @param obj the object
+ * @return {@code true} if they are equal, {@code false} otherwise
+ */
+ public boolean equals(final RealmNestedPrincipal obj) {
+ return this == obj || obj != null && r.equals(obj.r) && p.equals(obj.p);
+ }
+
+ /**
+ * Get this principal as a string.
+ *
+ * @return this principal as a string (not {@code null})
+ */
+ public String toString() {
+ return getName();
+ }
+
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ if (r == null || p == null) {
+ throw new InvalidObjectException("All fields must be non-null");
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/principal/package-info.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/principal/package-info.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/principal/package-info.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,23 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The principal types used by this API. Note that, as a matter of policy, principal types are defined by
+ * format (e.g. plain string, X.500 string, etc.), not by usage (e.g. user name, host name).
+ */
+package org.wildfly.security.auth.principal;
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/AggregateSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/AggregateSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/AggregateSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,277 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import static org.wildfly.common.Assert.checkNotNullParam;
+import static org.wildfly.security.auth.realm.ElytronMessages.log;
+
+import java.security.Principal;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.function.Function;
+
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.auth.server.event.RealmAuthenticationEvent;
+import org.wildfly.security.auth.server.event.RealmAuthorizationEvent;
+import org.wildfly.security.auth.server.event.RealmEvent;
+import org.wildfly.security.authz.AggregateAttributes;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.Evidence;
+
+/**
+ * A realm which directs authentication to one realm and authorization to another. The authentication realm need
+ * not provide any authorization information. Likewise the authorization realm need not provide any authentication
+ * credential acquisition or verification capabilities.
+ *
+ * @author David M. Lloyd
+ */
+public final class AggregateSecurityRealm implements SecurityRealm {
+ private final SecurityRealm authenticationRealm;
+ private final SecurityRealm[] authorizationRealms;
+ private final Function principalTransformer;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param authenticationRealm the realm to use for authentication
+ * @param authorizationRealm the realm to use for authorization
+ */
+ public AggregateSecurityRealm(final SecurityRealm authenticationRealm, final SecurityRealm authorizationRealm) {
+ this.authenticationRealm = checkNotNullParam("authenticationRealm", authenticationRealm);
+ checkNotNullParam("authorizationRealm", authorizationRealm);
+ this.authorizationRealms = new SecurityRealm[] { authorizationRealm };
+ this.principalTransformer = null;
+ }
+
+ public AggregateSecurityRealm(final SecurityRealm authenticationRealm, final SecurityRealm... authorizationRealms) {
+ this.authenticationRealm = checkNotNullParam("authenticationRealm", authenticationRealm);
+ this.authorizationRealms = checkNotNullParam("authorizationRealms", authorizationRealms);
+ this.principalTransformer = null;
+
+ }
+ public AggregateSecurityRealm(final SecurityRealm authenticationRealm, Function principalTransformer, final SecurityRealm... authorizationRealms) {
+ this.authenticationRealm = checkNotNullParam("authenticationRealm", authenticationRealm);
+ this.authorizationRealms = checkNotNullParam("authorizationRealms", authorizationRealms);
+ this.principalTransformer = principalTransformer;
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Evidence evidence) throws RealmUnavailableException {
+ boolean ok = false;
+ final RealmIdentity authenticationIdentity = authenticationRealm.getRealmIdentity(evidence);
+ if (authenticationIdentity.exists()) {
+ log.tracef("Authentication identity for principal [%s] found.", evidence.getDecodedPrincipal());
+ }
+ final RealmIdentity[] authorizationIdentities = new RealmIdentity[authorizationRealms.length];
+ try {
+ for (int i = 0; i < authorizationIdentities.length; i++) {
+ SecurityRealm authorizationRealm = authorizationRealms[i];
+ authorizationIdentities[i] = (authorizationRealm == authenticationRealm) ? authenticationIdentity
+ : getAuthorizationIdentity(authorizationRealm, evidence, principalTransformer, authenticationIdentity);
+ if (authorizationIdentities[i].exists()) {
+ log.tracef("Authorization identity for principal [%s] found.", evidence.getDecodedPrincipal());
+ }
+ }
+
+ final Identity identity = new Identity(authenticationIdentity, authorizationIdentities);
+ ok = true;
+ return identity;
+ } finally {
+ if (!ok) {
+ authenticationIdentity.dispose();
+ for (RealmIdentity current : authorizationIdentities) {
+ if (current != null)
+ current.dispose();
+ }
+ }
+ }
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUnavailableException {
+ boolean ok = false;
+ final RealmIdentity authenticationIdentity = authenticationRealm.getRealmIdentity(principal);
+ if (authenticationIdentity.exists()) {
+ log.tracef("Authentication identity for principal [%s] found.", principal);
+ }
+ Principal authorizationPrincipal = principal;
+ if (principalTransformer != null) {
+ authorizationPrincipal = principalTransformer.apply(authorizationPrincipal);
+ if (authorizationPrincipal == null) throw ElytronMessages.log.transformedPrincipalCannotBeNull();
+ }
+
+ final RealmIdentity[] authorizationIdentities = new RealmIdentity[authorizationRealms.length];
+ try {
+ for (int i = 0; i < authorizationIdentities.length; i++) {
+ SecurityRealm authorizationRealm = authorizationRealms[i];
+ authorizationIdentities[i] = (authorizationRealm == authenticationRealm) && (principalTransformer == null) ? authenticationIdentity : authorizationRealm.getRealmIdentity(authorizationPrincipal);
+ if (authorizationIdentities[i].exists()) {
+ log.tracef("Authorization identity for principal [%s] found.", principal);
+ }
+ }
+
+ final Identity identity = new Identity(authenticationIdentity, authorizationIdentities);
+ ok = true;
+ return identity;
+ } finally {
+ if (!ok) {
+ authenticationIdentity.dispose();
+ for (RealmIdentity current : authorizationIdentities) {
+ if (current != null)
+ current.dispose();
+ }
+ }
+ }
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return authenticationRealm.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ return authenticationRealm.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ private RealmIdentity getAuthorizationIdentity(SecurityRealm authorizationRealm, Evidence evidence, Function principalTransformer,
+ RealmIdentity authenticationIdentity) throws RealmUnavailableException {
+ if (principalTransformer == null) {
+ if (evidence.getPrincipal() == null) {
+ return authorizationRealm.getRealmIdentity(authenticationIdentity.getRealmIdentityPrincipal());
+ } else {
+ return authorizationRealm.getRealmIdentity(evidence);
+ }
+ } else {
+ if (evidence.getPrincipal() == null) {
+ Principal authorizationPrincipal = authenticationIdentity.getRealmIdentityPrincipal();
+ authorizationPrincipal = principalTransformer.apply(authorizationPrincipal);
+ if (authorizationPrincipal == null) throw ElytronMessages.log.transformedPrincipalCannotBeNull();
+ return authorizationRealm.getRealmIdentity(authorizationPrincipal);
+ } else {
+ return authorizationRealm.getRealmIdentity(evidence, principalTransformer);
+ }
+ }
+ }
+
+ @Override
+ public void handleRealmEvent(final RealmEvent event) {
+ if (event instanceof RealmAuthenticationEvent) {
+ authenticationRealm.handleRealmEvent(event);
+ } else if (event instanceof RealmAuthorizationEvent) {
+ for (SecurityRealm current : authorizationRealms) {
+ SecurityRealm.safeHandleRealmEvent(current, event);
+ }
+ } else {
+ // use safe wrapper to ensure both are called
+ SecurityRealm.safeHandleRealmEvent(authenticationRealm, event);
+ for (SecurityRealm current : authorizationRealms) {
+ SecurityRealm.safeHandleRealmEvent(current, event);
+ }
+ }
+ }
+
+ static final class Identity implements RealmIdentity {
+
+ private final RealmIdentity authenticationIdentity;
+ private final RealmIdentity[] authorizationIdentities;
+
+ Identity(final RealmIdentity authenticationIdentity, final RealmIdentity[] authorizationIdentities) {
+ this.authenticationIdentity = authenticationIdentity;
+ this.authorizationIdentities = authorizationIdentities;
+ }
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return authenticationIdentity.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return authenticationIdentity.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ return authenticationIdentity.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return authenticationIdentity.getCredential(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName) throws RealmUnavailableException {
+ return authenticationIdentity.getCredential(credentialType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType) throws RealmUnavailableException {
+ return authenticationIdentity.getCredential(credentialType);
+ }
+
+ @Override
+ public boolean verifyEvidence(final Evidence evidence) throws RealmUnavailableException {
+ return authenticationIdentity.verifyEvidence(evidence);
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ return authenticationIdentity.exists();
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ if (authorizationIdentities.length == 1) {
+ return authorizationIdentities[0].getAuthorizationIdentity();
+ }
+
+ final AuthorizationIdentity[] authorizationIdentities = new AuthorizationIdentity[this.authorizationIdentities.length];
+ for (int i = 0; i < authorizationIdentities.length; i++) {
+ authorizationIdentities[i] = this.authorizationIdentities[i].getAuthorizationIdentity();
+ }
+
+ // Use a Supplier here so we only load and aggregate the attributes if they are actually used.
+ return AuthorizationIdentity.basicIdentity(() -> combineAttributes(authorizationIdentities), "Aggregated");
+ }
+
+ private Attributes combineAttributes(AuthorizationIdentity[] authorizationIdentities) {
+ Attributes[] attributes = new Attributes[authorizationIdentities.length];
+ for (int i = 0; i < attributes.length; i++) {
+ attributes[i] = authorizationIdentities[i].getAttributes();
+ }
+
+ return AggregateAttributes.aggregateOf(attributes);
+ }
+
+ @Override
+ public void dispose() {
+ authenticationIdentity.dispose();
+ for (RealmIdentity current : authorizationIdentities) {
+ current.dispose();
+ }
+ }
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CacheableSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CacheableSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CacheableSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import java.security.Principal;
+import java.util.function.Consumer;
+
+import org.wildfly.security.auth.server.SecurityRealm;
+
+/**
+ * This interface defines a contract for a {@link SecurityRealm} that supports caching of {@link org.wildfly.security.auth.server.RealmIdentity} instances.
+ *
+ * @author Pedro Igor
+ * @see CachingSecurityRealm
+ */
+public interface CacheableSecurityRealm extends SecurityRealm {
+
+ /**
+ * Register a listener that should be invoked by this realm in order to notify the caching layer about changes to a specific identity.
+ *
+ * @param listener the listener
+ */
+ void registerIdentityChangeListener(Consumer listener);
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingModifiableSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingModifiableSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingModifiableSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,202 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import java.security.Principal;
+import java.security.Provider;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Collection;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.wildfly.common.function.ExceptionConsumer;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.ModifiableRealmIdentityIterator;
+import org.wildfly.security.auth.server.ModifiableRealmIdentity;
+import org.wildfly.security.auth.server.ModifiableSecurityRealm;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.cache.RealmIdentityCache;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.Evidence;
+
+/**
+ * A wrapper class that provides caching capabilities for a {@link org.wildfly.security.auth.server.ModifiableSecurityRealm} and its identities.
+ *
+ * @author Pedro Igor
+ */
+public class CachingModifiableSecurityRealm extends CachingSecurityRealm implements ModifiableSecurityRealm {
+
+ /**
+ * Creates a new instance.
+ *
+ * @param realm the {@link CacheableSecurityRealm} whose {@link RealmIdentity} should be cached.
+ * @param cache the {@link RealmIdentityCache} instance
+ */
+ public CachingModifiableSecurityRealm(CacheableSecurityRealm realm, RealmIdentityCache cache) {
+ super(realm, cache);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param realm the {@link CacheableSecurityRealm} whose {@link RealmIdentity} should be cached.
+ * @param cache the {@link RealmIdentityCache} instance
+ * @param providerSupplier the provider supplier to use for verification purposes (must not be {@code null})
+ */
+ public CachingModifiableSecurityRealm(CacheableSecurityRealm realm, RealmIdentityCache cache, Supplier providerSupplier) {
+ super(realm, cache, providerSupplier);
+ }
+
+ @Override
+ public ModifiableRealmIdentity getRealmIdentityForUpdate(Principal principal) throws RealmUnavailableException {
+ return wrap(getModifiableSecurityRealm().getRealmIdentityForUpdate(principal));
+ }
+
+ @Override
+ public ModifiableRealmIdentityIterator getRealmIdentityIterator() throws RealmUnavailableException {
+ ModifiableRealmIdentityIterator iterator = getModifiableSecurityRealm().getRealmIdentityIterator();
+ return new ModifiableRealmIdentityIterator() {
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public ModifiableRealmIdentity next() {
+ return wrap(iterator.next());
+ }
+ };
+ }
+
+ private ModifiableRealmIdentity wrap(final ModifiableRealmIdentity modifiable) {
+ return new ModifiableRealmIdentity() {
+ @Override
+ public void delete() throws RealmUnavailableException {
+ executeAndInvalidate(modifiable -> { modifiable.delete(); });
+ }
+
+ @Override
+ public void create() throws RealmUnavailableException {
+ modifiable.create();
+ }
+
+ @Override
+ public void setCredentials(Collection extends Credential> credentials) throws RealmUnavailableException {
+ executeAndInvalidate(modifiable -> { modifiable.setCredentials(credentials); });
+ }
+
+ @Override
+ public void setAttributes(Attributes attributes) throws RealmUnavailableException {
+ executeAndInvalidate(modifiable -> { modifiable.setAttributes(attributes); });
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return modifiable.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public C getCredential(Class credentialType) throws RealmUnavailableException {
+ return modifiable.getCredential(credentialType);
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(Class extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+ return modifiable.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
+ return modifiable.verifyEvidence(evidence);
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ return modifiable.exists();
+ }
+
+ @Override
+ public void updateCredential(Credential credential) throws RealmUnavailableException {
+ executeAndInvalidate(modifiable -> { modifiable.updateCredential(credential); });
+ }
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return modifiable.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public C getCredential(Class credentialType, String algorithmName) throws RealmUnavailableException {
+ return modifiable.getCredential(credentialType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return modifiable.getCredential(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public R applyToCredential(Class credentialType, Function function) throws RealmUnavailableException {
+ return modifiable.applyToCredential(credentialType, function);
+ }
+
+ @Override
+ public R applyToCredential(Class credentialType, String algorithmName, Function function) throws RealmUnavailableException {
+ return modifiable.applyToCredential(credentialType, algorithmName, function);
+ }
+
+ @Override
+ public R applyToCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec, final Function function) throws RealmUnavailableException {
+ return modifiable.applyToCredential(credentialType, algorithmName, parameterSpec, function);
+ }
+
+ @Override
+ public void dispose() {
+ modifiable.dispose();
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ return modifiable.getAuthorizationIdentity();
+ }
+
+ @Override
+ public Attributes getAttributes() throws RealmUnavailableException {
+ return modifiable.getAttributes();
+ }
+
+ private void executeAndInvalidate(ExceptionConsumer operation) throws RealmUnavailableException {
+ try {
+ operation.accept(modifiable);
+ } catch (RealmUnavailableException rue) {
+ throw rue;
+ } finally {
+ removeFromCache(modifiable.getRealmIdentityPrincipal());
+ }
+ }
+ };
+ }
+
+ private ModifiableSecurityRealm getModifiableSecurityRealm() {
+ return (ModifiableSecurityRealm) getCacheableRealm();
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/CachingSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,327 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import static org.wildfly.common.Assert.checkNotNullParam;
+import static org.wildfly.security.auth.realm.ElytronMessages.log;
+import static org.wildfly.security.provider.util.ProviderUtil.INSTALLED_PROVIDERS;
+
+import java.security.Principal;
+import java.security.Provider;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.function.Supplier;
+
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.IdentityCredentials;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.auth.server.event.RealmEvent;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.cache.RealmIdentityCache;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.credential.PasswordCredential;
+import org.wildfly.security.evidence.Evidence;
+import org.wildfly.security.evidence.PasswordGuessEvidence;
+import org.wildfly.security.password.Password;
+import org.wildfly.security.password.interfaces.ClearPassword;
+
+/**
+ * A wrapper class that provides caching capabilities for a {@link SecurityRealm} and its identities.
+ *
+ * @author Pedro Igor
+ */
+public class CachingSecurityRealm implements SecurityRealm {
+
+ private final Supplier providerSupplier;
+ private final SecurityRealm realm;
+ private final RealmIdentityCache cache;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param realm the {@link SecurityRealm} whose {@link RealmIdentity} should be cached.
+ * @param cache the {@link RealmIdentityCache} instance
+ */
+ public CachingSecurityRealm(SecurityRealm realm, RealmIdentityCache cache) {
+ this(realm, cache, INSTALLED_PROVIDERS);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param realm the {@link SecurityRealm} whose {@link RealmIdentity} should be cached.
+ * @param cache the {@link RealmIdentityCache} instance
+ * @param providerSupplier the provider supplier to use for verification purposes (must not be {@code null})
+ */
+ public CachingSecurityRealm(SecurityRealm realm, RealmIdentityCache cache, Supplier providerSupplier) {
+ this.realm = checkNotNullParam("realm", realm);
+ this.cache = checkNotNullParam("cache", cache);
+ this.providerSupplier = checkNotNullParam("providers", providerSupplier);
+
+ if (realm instanceof CacheableSecurityRealm) {
+ CacheableSecurityRealm cacheable = CacheableSecurityRealm.class.cast(realm);
+ cacheable.registerIdentityChangeListener(this::removeFromCache);
+ } else {
+ throw ElytronMessages.log.realmCacheUnexpectedType(realm, CacheableSecurityRealm.class);
+ }
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(Principal principal) throws RealmUnavailableException {
+ RealmIdentity cached = cache.get(principal);
+
+ if (cached != null) {
+ log.tracef("Returning cached RealmIdentity for '%s'", principal);
+ return cached;
+ }
+
+ RealmIdentity realmIdentity = getCacheableRealm().getRealmIdentity(principal);
+
+ if (!realmIdentity.exists()) {
+ log.tracef("RealmIdentity for '%s' does not exist, skipping cache.'", principal);
+ return realmIdentity;
+ }
+
+ RealmIdentity cachedIdentity = new RealmIdentity() {
+ final RealmIdentity identity = realmIdentity;
+
+ AuthorizationIdentity authorizationIdentity = null;
+ Attributes attributes = null;
+ IdentityCredentials credentials = IdentityCredentials.NONE;
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return identity.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ if (credentials.contains(credentialType, algorithmName, parameterSpec)) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredentialAcquireSupport credentialType='%s' with algorithmName='%' known for pincipal='%s'", credentialType.getName(), algorithmName, principal.getName());
+ }
+ return credentials.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+ Credential credential = identity.getCredential(credentialType, algorithmName, parameterSpec);
+ if (credential != null) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredentialAcquireSupport Credential for credentialType='%s' with algorithmName='%' obtained from identity - caching for principal='%s'",
+ credentialType.getName(), algorithmName, principal.getName());
+ }
+ credentials = credentials.withCredential(credential);
+ }
+ return credentials.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public C getCredential(Class credentialType) throws RealmUnavailableException {
+ if (credentials.contains(credentialType)) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' cached, returning cached credential for principal='%s'", credentialType.getName(), principal.getName());
+ }
+ return credentials.getCredential(credentialType);
+ }
+ Credential credential = identity.getCredential(credentialType);
+ if (credential != null) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' obtained from identity - caching for principal='%s'", credentialType.getName(), principal.getName());
+ }
+ credentials = credentials.withCredential(credential);
+ }
+ return credentials.getCredential(credentialType);
+ }
+
+ @Override
+ public C getCredential(Class credentialType, String algorithmName) throws RealmUnavailableException {
+ if (credentials.contains(credentialType, algorithmName)) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' with algorithmName='%' cached, returning cached credential for principal='%s'", credentialType.getName(), algorithmName, principal.getName());
+ }
+ return credentials.getCredential(credentialType, algorithmName);
+ }
+ Credential credential = identity.getCredential(credentialType, algorithmName);
+ if (credential != null) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' with algorithmName='%' obtained from identity - caching.", credentialType.getName(), algorithmName);
+ }
+ credentials = credentials.withCredential(credential);
+ }
+ return credentials.getCredential(credentialType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ if (credentials.contains(credentialType, algorithmName, parameterSpec)) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' with algorithmName='%' cached, returning cached credential for principal='%s'", credentialType.getName(), algorithmName, principal.getName());
+ }
+ return credentials.getCredential(credentialType, algorithmName, parameterSpec);
+ }
+ Credential credential = identity.getCredential(credentialType, algorithmName, parameterSpec);
+ if (credential != null) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getCredential credentialType='%s' with algorithmName='%' obtained from identity - caching for principal='%s'", credentialType.getName(), algorithmName, principal.getName());
+ }
+ credentials = credentials.withCredential(credential);
+ }
+ return credentials.getCredential(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public void updateCredential(Credential credential) throws RealmUnavailableException {
+ log.tracef("updateCredential For principal='%s'", principal);
+ try {
+ identity.updateCredential(credential);
+ } finally {
+ removeFromCache(identity.getRealmIdentityPrincipal());
+ }
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(Class extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+ if (PasswordGuessEvidence.class.isAssignableFrom(evidenceType)) {
+ if (credentials.canVerify(evidenceType, algorithmName)) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getEvidenceVerifySupport evidenceType='%s' with algorithmName='%' can verify from cache for principal='%s'", evidenceType.getName(), algorithmName, principal.getName());
+ }
+ return SupportLevel.SUPPORTED;
+ }
+ Credential credential = identity.getCredential(PasswordCredential.class);
+ if (credential != null) {
+ if (log.isTraceEnabled()) {
+ log.tracef("getEvidenceVerifySupport evidenceType='%s' with algorithmName='%' credential obtained from identity and cached for principal='%s'",
+ evidenceType.getName(), algorithmName, principal.getName());
+ }
+ credentials = credentials.withCredential(credential);
+ if (credential.canVerify(evidenceType, algorithmName)) {
+ return SupportLevel.SUPPORTED;
+ }
+ }
+ }
+ if (log.isTraceEnabled()) {
+ log.tracef("getEvidenceVerifySupport evidenceType='%s' with algorithmName='%' falling back to direct support of identity for principal='%s'",
+ evidenceType.getName(), algorithmName, principal.getName());
+ }
+ return identity.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
+ if (evidence instanceof PasswordGuessEvidence) {
+ if (credentials.canVerify(evidence)) {
+ log.tracef("verifyEvidence For principal='%s' using cached credential", principal);
+ return credentials.verify(providerSupplier, evidence);
+ }
+ Credential credential = identity.getCredential(PasswordCredential.class);
+ if (credential != null) {
+ log.tracef("verifyEvidence Credential obtained from identity and cached for principal='%s'", principal);
+ credentials = credentials.withCredential(credential);
+ if (credential.canVerify(evidence)) {
+ return credential.verify(providerSupplier, evidence);
+ }
+ }
+ char[] guess = ((PasswordGuessEvidence) evidence).getGuess();
+ Password password = ClearPassword.createRaw(ClearPassword.ALGORITHM_CLEAR, guess);
+ log.tracef("verifyEvidence Falling back to direct support of identity for principal='%s'", principal);
+ if (identity.verifyEvidence(evidence)) {
+ credentials = credentials.withCredential(new PasswordCredential(password));
+ return true;
+ }
+ return false;
+ }
+ return identity.verifyEvidence(evidence);
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ return true; // non-existing identities will not be wrapped
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ if (authorizationIdentity == null) {
+ log.tracef("getAuthorizationIdentity Caching AuthorizationIdentity for principal='%s'", principal);
+ authorizationIdentity = identity.getAuthorizationIdentity();
+ }
+ return authorizationIdentity;
+ }
+
+ @Override
+ public Attributes getAttributes() throws RealmUnavailableException {
+ if (attributes == null) {
+ log.tracef("getAttributes Caching Attributes for principal='%s'", principal);
+ attributes = identity.getAttributes();
+ }
+ return attributes;
+ }
+
+ @Override
+ public void dispose() {
+ identity.dispose();
+ }
+ };
+
+ log.tracef("Created wrapper RealmIdentity for '%s' and placing in cache.", principal);
+ cache.put(principal, cachedIdentity);
+
+ return cachedIdentity;
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return getCacheableRealm().getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(Class extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+ return getCacheableRealm().getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public void handleRealmEvent(RealmEvent event) {
+ getCacheableRealm().handleRealmEvent(event);
+ }
+
+ /**
+ * Removes a {@link RealmIdentity} referenced by the specified {@link Principal} from the cache.
+ *
+ * @param principal the {@link Principal} that references a previously cached realm identity
+ */
+ public void removeFromCache(Principal principal) {
+ cache.remove(principal);
+ }
+
+ /**
+ * Removes all cached identities from the cache.
+ */
+ public void removeAllFromCache() {
+ cache.clear();
+ }
+
+ /**
+ * Gets wrapped backing realm.
+ *
+ * @return the wrapped backing realm
+ */
+ protected SecurityRealm getCacheableRealm() {
+ return realm;
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/DistributedSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/DistributedSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/DistributedSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,293 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2020 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.realm;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.AlgorithmEvidence;
+import org.wildfly.security.evidence.Evidence;
+
+import java.security.Principal;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.function.Consumer;
+
+/**
+ * A realm for authentication and authorization of identities distributed between multiple realms.
+ *
+ * @author Martin Mazanek
+ */
+public class DistributedSecurityRealm implements SecurityRealm {
+ private final boolean ignoreUnavailableRealms;
+ private final SecurityRealm[] securityRealms;
+ private final Consumer unavailableRealmCallback;
+
+ public DistributedSecurityRealm(final SecurityRealm... securityRealms) {
+ this(false, null, securityRealms);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param ignoreUnavailableRealms allow to specify that the search should continue on to the next realm if a realm happens to be unavailable
+ * @param unavailableRealmCallback a callback that can be used to emit realm unavailability, can be {@code null}
+ * @param securityRealms references to one or more security realms for authentication and authorization
+ */
+ public DistributedSecurityRealm( final boolean ignoreUnavailableRealms, final Consumer unavailableRealmCallback, final SecurityRealm... securityRealms) {
+ Assert.checkNotNullParam("securityRealms", securityRealms);
+ this.ignoreUnavailableRealms = ignoreUnavailableRealms;
+ this.unavailableRealmCallback = unavailableRealmCallback;
+ this.securityRealms = securityRealms;
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Evidence evidence) throws RealmUnavailableException {
+ return new EvidenceDistributedIdentity(evidence);
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUnavailableException {
+ return new PrincipalDistributedIdentity(principal);
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ SupportLevel max = SupportLevel.UNSUPPORTED;
+ for (SecurityRealm r : securityRealms) {
+ max = SupportLevel.max(max, r.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec));
+ }
+ return max;
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ SupportLevel max = SupportLevel.UNSUPPORTED;
+ for (SecurityRealm r : securityRealms) {
+ max = SupportLevel.max(max, r.getEvidenceVerifySupport(evidenceType, algorithmName));
+ }
+ return max;
+ }
+
+ final class EvidenceDistributedIdentity implements RealmIdentity {
+ private final Evidence evidence;
+ private final String evidenceAlgorithm;
+ private RealmIdentity currentIdentity = RealmIdentity.NON_EXISTENT;
+ private int nextRealm = 0;
+
+ private EvidenceDistributedIdentity(Evidence evidence) throws RealmUnavailableException {
+ this.evidence = evidence;
+ if (evidence instanceof AlgorithmEvidence) {
+ evidenceAlgorithm = ((AlgorithmEvidence) evidence).getAlgorithm();
+ } else {
+ evidenceAlgorithm = null;
+ }
+ nextIdentity();
+ }
+
+ private boolean nextIdentity() throws RealmUnavailableException {
+ currentIdentity.dispose();
+ if (nextRealm >= securityRealms.length) {
+ currentIdentity = RealmIdentity.NON_EXISTENT;
+ return false;
+ }
+ if (securityRealms[nextRealm].getEvidenceVerifySupport(evidence.getClass(), evidenceAlgorithm).mayBeSupported()) {
+ currentIdentity = securityRealms[nextRealm].getRealmIdentity(evidence);
+ nextRealm++;
+ if (currentIdentity.getEvidenceVerifySupport(evidence.getClass(), evidenceAlgorithm).isNotSupported()) {
+ return nextIdentity();
+ }
+ } else {
+ nextRealm++;
+ return nextIdentity();
+ }
+ return true;
+ }
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return currentIdentity.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ // Identity created from evidence will be verified using the evidence
+ return SupportLevel.UNSUPPORTED;
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ //as server verifies evidence with same evidence used for creating realm identity, we dont have to look into remaining realms for support (currentIdentity will always support evidence verification, unless none of the possible does)
+ return currentIdentity.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return null;
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName) throws RealmUnavailableException {
+ return null;
+ }
+
+ @Override
+ public C getCredential(final Class credentialType) throws RealmUnavailableException {
+ return null;
+ }
+
+ @Override
+ public boolean verifyEvidence(final Evidence evidence) throws RealmUnavailableException {
+ do {
+ if (currentIdentity.verifyEvidence(evidence)) {
+ return true;
+ }
+ } while (nextIdentity());
+ return false;
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ return currentIdentity.exists();
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ return currentIdentity.getAuthorizationIdentity();
+ }
+
+ @Override
+ public void dispose() {
+ currentIdentity.dispose();
+ }
+ }
+
+ final class PrincipalDistributedIdentity implements RealmIdentity {
+
+ private final Principal principal;
+ private RealmIdentity currentIdentity = RealmIdentity.NON_EXISTENT;
+ private int nextRealm = 0;
+
+ PrincipalDistributedIdentity(Principal principal) throws RealmUnavailableException {
+ this.principal = principal;
+ nextIdentity();
+ }
+
+ private boolean nextIdentity() throws RealmUnavailableException {
+ currentIdentity.dispose();
+ if (nextRealm >= securityRealms.length) {
+ currentIdentity = RealmIdentity.NON_EXISTENT;
+ return false;
+ }
+
+ boolean doesIdentityExist = false;
+ try {
+ currentIdentity = securityRealms[nextRealm].getRealmIdentity(principal);
+ doesIdentityExist = currentIdentity.exists();
+ } catch (RealmUnavailableException e) {
+ if (!ignoreUnavailableRealms) {
+ throw e;
+ }
+ ElytronMessages.log.realmIsNotAvailable(e);
+ if (unavailableRealmCallback != null) {
+ unavailableRealmCallback.accept(nextRealm);
+ }
+ }
+ nextRealm++;
+ if (!doesIdentityExist) {
+ return nextIdentity();
+ }
+ return true;
+ }
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return currentIdentity.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return currentIdentity.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ return currentIdentity.getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ do {
+ C credential = currentIdentity.getCredential(credentialType, algorithmName, parameterSpec);
+ if (credential != null) {
+ return credential;
+ }
+ } while (nextIdentity());
+
+ return null;
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName) throws RealmUnavailableException {
+ do {
+ C credential = currentIdentity.getCredential(credentialType, algorithmName);
+ if (credential != null) {
+ return credential;
+ }
+ } while (nextIdentity());
+
+ return null;
+ }
+
+ @Override
+ public C getCredential(final Class credentialType) throws RealmUnavailableException {
+ do {
+ C credential = currentIdentity.getCredential(credentialType);
+ if (credential != null) {
+ return credential;
+ }
+ } while (nextIdentity());
+
+ return null;
+ }
+
+ @Override
+ public boolean verifyEvidence(final Evidence evidence) throws RealmUnavailableException {
+ return currentIdentity.verifyEvidence(evidence);
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ return currentIdentity.exists();
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ return currentIdentity.getAuthorizationIdentity();
+ }
+
+ @Override
+ public void dispose() {
+ currentIdentity.dispose();
+ }
+ }
+
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.realm;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.security.KeyStoreException;
+import java.security.Principal;
+import java.util.NoSuchElementException;
+
+import org.jboss.logging.BasicLogger;
+import org.jboss.logging.Logger;
+import org.jboss.logging.annotations.Cause;
+import org.jboss.logging.annotations.LogMessage;
+import org.jboss.logging.annotations.Message;
+import org.jboss.logging.annotations.MessageLogger;
+import org.jboss.logging.annotations.Param;
+import org.jboss.logging.annotations.ValidIdRange;
+import org.jboss.logging.annotations.ValidIdRanges;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+/**
+ * Log messages and exceptions for Elytron.
+ *
+ * @author David M. Lloyd
+ * @author Darran Lofthouse
+ */
+@MessageLogger(projectCode = "ELY", length = 5)
+@ValidIdRanges({
+ @ValidIdRange(min = 1006, max = 1082),
+ @ValidIdRange(min = 1138, max = 1154),
+ @ValidIdRange(min = 11005, max = 11005),
+ @ValidIdRange(min = 13000, max = 13999)
+})
+interface ElytronMessages extends BasicLogger {
+ ElytronMessages log = Logger.getMessageLogger(ElytronMessages.class, "org.wildfly.security");
+
+ @Message(id = 1006, value = "No realm name found in users property file - non-plain-text users file must contain \"#$REALM_NAME=RealmName$\" line")
+ RealmUnavailableException noRealmFoundInProperties();
+
+ @LogMessage(level = Logger.Level.DEBUG)
+ @Message(id = 1007, value = "JAAS authentication failed for principal %s")
+ void debugInfoJaasAuthenticationFailure(Principal principal, @Cause Throwable cause);
+
+ @Message(id = 1008, value = "Failed to create login context")
+ RealmUnavailableException failedToCreateLoginContext(@Cause Throwable cause);
+
+ @Message(id = 1009, value = "Failed to instantiate custom CallbackHandler")
+ RealmUnavailableException failedToInstantiateCustomHandler(@Cause Throwable cause);
+
+ @Message(id = 1012, value = "Filesystem-backed realm unexpectedly failed to open path \"%s\" for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmFailedToOpen(Path path, String finalName, @Cause IOException cause);
+
+ @Message(id = 1013, value = "Filesystem-backed realm unexpectedly failed to read path \"%s\" for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmFailedToRead(Path path, String finalName, @Cause Exception cause);
+
+ @Message(id = 1015, value = "Filesystem-backed realm encountered invalid file content in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmInvalidContent(Path path, int lineNumber, String name);
+
+ @Message(id = 1016, value = "Filesystem-backed realm encountered missing required attribute \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmMissingAttribute(String attribute, Path path, int lineNumber, String name);
+
+ @Message(id = 1017, value = "Filesystem-backed realm encountered invalid password format \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmInvalidPasswordFormat(String format, Path path, int lineNumber, String name);
+
+ @Message(id = 1018, value = "Filesystem-backed realm encountered invalid password algorithm \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmInvalidPasswordAlgorithm(String algorithm, Path path, int lineNumber, String name);
+
+ @Message(id = 1020, value = "Filesystem-backed realm failed to update identity \"%s\"")
+ RealmUnavailableException fileSystemUpdatedFailed(String name, @Cause Throwable cause);
+
+ @Message(id = 1021, value = "Filesystem-backed realm failed to delete identity \"%s\"")
+ RealmUnavailableException fileSystemRealmDeleteFailed(String name, @Cause IOException e);
+
+ @Message(id = 1022, value = "Filesystem-backed realm failed to find identity \"%s\"")
+ RealmUnavailableException fileSystemRealmNotFound(String name);
+
+ @Message(id = 1023, value = "Filesystem-backed realm failed to write to file \"%s\" for identity \"%s\"")
+ RealmUnavailableException fileSystemRealmFailedToWrite(Path tempPath, String name, @Cause Exception e);
+
+ @Message(id = 1024, value = "Filesystem-backed realm cannot create duplicate identity for identity \"%s\"")
+ RealmUnavailableException fileSystemRealmAlreadyExists(String name, @Cause Throwable e);
+
+ @Message(id = 1025, value = "Filesystem-backed realm encountered invalid certificate format \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmCertificateReadError(String format, Path path, int lineNumber, String name);
+
+ @Message(id = 1026, value = "Filesystem-backed realm encountered invalid key format \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmUnsupportedKeyFormat(String format, Path path, int lineNumber, String name);
+
+ @Message(id = 1027, value = "Filesystem-backed realm encountered invalid key algorithm for format \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmUnsupportedKeyAlgorithm(String format, Path path, int lineNumber, String name, @Cause Exception e);
+
+ @Message(id = 1064, value = "Invalid identity name")
+ IllegalArgumentException invalidName();
+
+ @Message(id = 1081, value = "Filesystem-backed realm encountered invalid OTP definition in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmInvalidOtpDefinition(Path path, int lineNumber, String name, @Cause Throwable cause);
+
+ @Message(id = 1082, value = "Filesystem-backed realm encountered invalid OTP algorithm \"%s\" in path \"%s\" line %d for identity name \"%s\"")
+ RealmUnavailableException fileSystemRealmInvalidOtpAlgorithm(String algorithm, Path path, int lineNumber, String name, @Cause Throwable cause);
+
+ @Message(id = 1138, value = "Decoding hashed password from users property file failed - should not be set as plain-text property file?")
+ RealmUnavailableException decodingHashedPasswordFromPropertiesRealmFailed(@Cause Exception e);
+
+ @Message(id = 1145, value = "Security realm [%s] must implement [%s]")
+ IllegalArgumentException realmCacheUnexpectedType(SecurityRealm realm, Class extends CacheableSecurityRealm> expectedType);
+
+ @Message(id = 13000, value = "Authorization principal cannot be null after transformation")
+ IllegalStateException transformedPrincipalCannotBeNull();
+
+ @Message(id = 1154, value = "Failed to read key store")
+ RealmUnavailableException failedToReadKeyStore(@Cause KeyStoreException e);
+
+ @Message(id = 11005, value = "Invalid unicode endoding, offending sequence: %s.")
+ IOException invalidUnicodeSequence(String s, @Cause NoSuchElementException nsee);
+
+ @LogMessage(level = Logger.Level.WARN)
+ @Message(id = 13001, value = "Realm is failing over.")
+ void realmFailover(@Cause RealmUnavailableException rue);
+
+ @Message(id = 13002, value = "%s does not handle a callback of type %s")
+ UnsupportedCallbackException unableToHandleCallback(@Param Callback callback, String callbackHandler, String callbackType);
+
+ @Message(id = 13003, value = "Failed to load JAAS configuration file.")
+ RealmUnavailableException failedToLoadJaasConfigFile();
+
+ @LogMessage(level = Logger.Level.DEBUG)
+ @Message(id = 13004, value = "JAAS logout failed for principal %s")
+ void debugInfoJaasLogoutFailure(Principal principal, @Cause Throwable cause);
+
+ @Message(id = 13005, value = "Filesystem-backed realm unable to decrypt identity")
+ RealmUnavailableException fileSystemRealmDecryptionFailed(@Cause Throwable cause);
+
+ @Message(id = 13006, value = "Filesystem-backed realm unable to encrypt identity")
+ RealmUnavailableException fileSystemRealmEncryptionFailed(@Cause Throwable cause);
+
+ @Message(id = 13007, value = "Signature for the following identity is invalid: %s.")
+ IntegrityException invalidIdentitySignature(String s);
+
+ @Message(id = 13008, value = "Unable to create a signature for the file: %s.")
+ RealmUnavailableException unableToGenerateSignature(String s);
+
+ @Message(id = 13009, value = "Unable to locate the signature element for the file: %s")
+ RealmUnavailableException cannotFindSignature(String s);
+
+ @Message(id = 13010, value = "Both PrivateKey and PublicKey must be defined for realm at: %s")
+ IllegalArgumentException invalidKeyPairArgument(String s);
+
+ @Message(id = 13011, value = "Integrity has not been enabled for the realm at: %s")
+ IllegalArgumentException integrityNotEnabled(String s);
+
+ @LogMessage(level = Logger.Level.WARN)
+ @Message(id = 13012, value = "A realm within the distributed realm is unavailable. This realm will be ignored.")
+ void realmIsNotAvailable(@Cause Exception e);
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages_$logger.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages_$logger.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/ElytronMessages_$logger.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,383 @@
+package org.wildfly.security.auth.realm;
+
+import java.util.Locale;
+import java.nio.file.Path;
+import java.lang.IllegalStateException;
+import java.io.Serializable;
+import javax.annotation.Generated;
+import org.jboss.logging.DelegatingBasicLogger;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.auth.realm.IntegrityException;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import java.lang.String;
+import java.io.IOException;
+import java.security.KeyStoreException;
+import org.jboss.logging.Logger;
+import java.lang.Exception;
+import javax.security.auth.callback.Callback;
+import org.jboss.logging.BasicLogger;
+import java.lang.Throwable;
+import java.lang.Class;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.util.Arrays;
+import java.security.Principal;
+import java.lang.IllegalArgumentException;
+import java.util.NoSuchElementException;
+
+
+import static org.jboss.logging.Logger.Level.DEBUG;
+import static org.jboss.logging.Logger.Level.WARN;
+
+/**
+ * Warning this class consists of generated code.
+ */
+@Generated(value = "org.jboss.logging.processor.generator.model.MessageLoggerImplementor", date = "2024-01-15T21:46:10+0100")
+public class ElytronMessages_$logger extends DelegatingBasicLogger implements ElytronMessages, BasicLogger, Serializable {
+ private static final long serialVersionUID = 1L;
+ private static final String FQCN = ElytronMessages_$logger.class.getName();
+ public ElytronMessages_$logger(final Logger log) {
+ super(log);
+ }
+ private static final Locale LOCALE = Locale.ROOT;
+ protected Locale getLoggingLocale() {
+ return LOCALE;
+ }
+ protected String noRealmFoundInProperties$str() {
+ return "ELY01006: No realm name found in users property file - non-plain-text users file must contain \"#$REALM_NAME=RealmName$\" line";
+ }
+ @Override
+ public final RealmUnavailableException noRealmFoundInProperties() {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), noRealmFoundInProperties$str()));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ private static void _copyStackTraceMinusOne(final Throwable e) {
+ final StackTraceElement[] st = e.getStackTrace();
+ e.setStackTrace(Arrays.copyOfRange(st, 1, st.length));
+ }
+ @Override
+ public final void debugInfoJaasAuthenticationFailure(final Principal principal, final Throwable cause) {
+ super.log.logf(FQCN, DEBUG, cause, debugInfoJaasAuthenticationFailure$str(), principal);
+ }
+ protected String debugInfoJaasAuthenticationFailure$str() {
+ return "ELY01007: JAAS authentication failed for principal %s";
+ }
+ protected String failedToCreateLoginContext$str() {
+ return "ELY01008: Failed to create login context";
+ }
+ @Override
+ public final RealmUnavailableException failedToCreateLoginContext(final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), failedToCreateLoginContext$str()), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String failedToInstantiateCustomHandler$str() {
+ return "ELY01009: Failed to instantiate custom CallbackHandler";
+ }
+ @Override
+ public final RealmUnavailableException failedToInstantiateCustomHandler(final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), failedToInstantiateCustomHandler$str()), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmFailedToOpen$str() {
+ return "ELY01012: Filesystem-backed realm unexpectedly failed to open path \"%s\" for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmFailedToOpen(final Path path, final String finalName, final IOException cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmFailedToOpen$str(), path, finalName), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmFailedToRead$str() {
+ return "ELY01013: Filesystem-backed realm unexpectedly failed to read path \"%s\" for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmFailedToRead(final Path path, final String finalName, final Exception cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmFailedToRead$str(), path, finalName), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmInvalidContent$str() {
+ return "ELY01015: Filesystem-backed realm encountered invalid file content in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmInvalidContent(final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmInvalidContent$str(), path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmMissingAttribute$str() {
+ return "ELY01016: Filesystem-backed realm encountered missing required attribute \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmMissingAttribute(final String attribute, final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmMissingAttribute$str(), attribute, path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmInvalidPasswordFormat$str() {
+ return "ELY01017: Filesystem-backed realm encountered invalid password format \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmInvalidPasswordFormat(final String format, final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmInvalidPasswordFormat$str(), format, path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmInvalidPasswordAlgorithm$str() {
+ return "ELY01018: Filesystem-backed realm encountered invalid password algorithm \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmInvalidPasswordAlgorithm(final String algorithm, final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmInvalidPasswordAlgorithm$str(), algorithm, path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemUpdatedFailed$str() {
+ return "ELY01020: Filesystem-backed realm failed to update identity \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemUpdatedFailed(final String name, final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemUpdatedFailed$str(), name), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmDeleteFailed$str() {
+ return "ELY01021: Filesystem-backed realm failed to delete identity \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmDeleteFailed(final String name, final IOException e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmDeleteFailed$str(), name), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmNotFound$str() {
+ return "ELY01022: Filesystem-backed realm failed to find identity \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmNotFound(final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmNotFound$str(), name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmFailedToWrite$str() {
+ return "ELY01023: Filesystem-backed realm failed to write to file \"%s\" for identity \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmFailedToWrite(final Path tempPath, final String name, final Exception e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmFailedToWrite$str(), tempPath, name), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmAlreadyExists$str() {
+ return "ELY01024: Filesystem-backed realm cannot create duplicate identity for identity \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmAlreadyExists(final String name, final Throwable e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmAlreadyExists$str(), name), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmCertificateReadError$str() {
+ return "ELY01025: Filesystem-backed realm encountered invalid certificate format \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmCertificateReadError(final String format, final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmCertificateReadError$str(), format, path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmUnsupportedKeyFormat$str() {
+ return "ELY01026: Filesystem-backed realm encountered invalid key format \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmUnsupportedKeyFormat(final String format, final Path path, final int lineNumber, final String name) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmUnsupportedKeyFormat$str(), format, path, lineNumber, name));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmUnsupportedKeyAlgorithm$str() {
+ return "ELY01027: Filesystem-backed realm encountered invalid key algorithm for format \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmUnsupportedKeyAlgorithm(final String format, final Path path, final int lineNumber, final String name, final Exception e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmUnsupportedKeyAlgorithm$str(), format, path, lineNumber, name), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String invalidName$str() {
+ return "ELY01064: Invalid identity name";
+ }
+ @Override
+ public final IllegalArgumentException invalidName() {
+ final IllegalArgumentException result = new IllegalArgumentException(String.format(getLoggingLocale(), invalidName$str()));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmInvalidOtpDefinition$str() {
+ return "ELY01081: Filesystem-backed realm encountered invalid OTP definition in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmInvalidOtpDefinition(final Path path, final int lineNumber, final String name, final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmInvalidOtpDefinition$str(), path, lineNumber, name), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmInvalidOtpAlgorithm$str() {
+ return "ELY01082: Filesystem-backed realm encountered invalid OTP algorithm \"%s\" in path \"%s\" line %d for identity name \"%s\"";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmInvalidOtpAlgorithm(final String algorithm, final Path path, final int lineNumber, final String name, final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmInvalidOtpAlgorithm$str(), algorithm, path, lineNumber, name), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String decodingHashedPasswordFromPropertiesRealmFailed$str() {
+ return "ELY01138: Decoding hashed password from users property file failed - should not be set as plain-text property file?";
+ }
+ @Override
+ public final RealmUnavailableException decodingHashedPasswordFromPropertiesRealmFailed(final Exception e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), decodingHashedPasswordFromPropertiesRealmFailed$str()), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String realmCacheUnexpectedType$str() {
+ return "ELY01145: Security realm [%s] must implement [%s]";
+ }
+ @Override
+ public final IllegalArgumentException realmCacheUnexpectedType(final SecurityRealm realm, final Class extends CacheableSecurityRealm> expectedType) {
+ final IllegalArgumentException result = new IllegalArgumentException(String.format(getLoggingLocale(), realmCacheUnexpectedType$str(), realm, expectedType));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String transformedPrincipalCannotBeNull$str() {
+ return "ELY13000: Authorization principal cannot be null after transformation";
+ }
+ @Override
+ public final IllegalStateException transformedPrincipalCannotBeNull() {
+ final IllegalStateException result = new IllegalStateException(String.format(getLoggingLocale(), transformedPrincipalCannotBeNull$str()));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String failedToReadKeyStore$str() {
+ return "ELY01154: Failed to read key store";
+ }
+ @Override
+ public final RealmUnavailableException failedToReadKeyStore(final KeyStoreException e) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), failedToReadKeyStore$str()), e);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String invalidUnicodeSequence$str() {
+ return "ELY11005: Invalid unicode endoding, offending sequence: %s.";
+ }
+ @Override
+ public final IOException invalidUnicodeSequence(final String s, final NoSuchElementException nsee) {
+ final IOException result = new IOException(String.format(getLoggingLocale(), invalidUnicodeSequence$str(), s), nsee);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ @Override
+ public final void realmFailover(final RealmUnavailableException rue) {
+ super.log.logf(FQCN, WARN, rue, realmFailover$str());
+ }
+ protected String realmFailover$str() {
+ return "ELY13001: Realm is failing over.";
+ }
+ protected String unableToHandleCallback$str() {
+ return "ELY13002: %s does not handle a callback of type %s";
+ }
+ @Override
+ public final UnsupportedCallbackException unableToHandleCallback(final Callback callback, final String callbackHandler, final String callbackType) {
+ final UnsupportedCallbackException result = new UnsupportedCallbackException(callback, String.format(getLoggingLocale(), unableToHandleCallback$str(), callbackHandler, callbackType));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String failedToLoadJaasConfigFile$str() {
+ return "ELY13003: Failed to load JAAS configuration file.";
+ }
+ @Override
+ public final RealmUnavailableException failedToLoadJaasConfigFile() {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), failedToLoadJaasConfigFile$str()));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ @Override
+ public final void debugInfoJaasLogoutFailure(final Principal principal, final Throwable cause) {
+ super.log.logf(FQCN, DEBUG, cause, debugInfoJaasLogoutFailure$str(), principal);
+ }
+ protected String debugInfoJaasLogoutFailure$str() {
+ return "ELY13004: JAAS logout failed for principal %s";
+ }
+ protected String fileSystemRealmDecryptionFailed$str() {
+ return "ELY13005: Filesystem-backed realm unable to decrypt identity";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmDecryptionFailed(final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmDecryptionFailed$str()), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String fileSystemRealmEncryptionFailed$str() {
+ return "ELY13006: Filesystem-backed realm unable to encrypt identity";
+ }
+ @Override
+ public final RealmUnavailableException fileSystemRealmEncryptionFailed(final Throwable cause) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), fileSystemRealmEncryptionFailed$str()), cause);
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String invalidIdentitySignature$str() {
+ return "ELY13007: Signature for the following identity is invalid: %s.";
+ }
+ @Override
+ public final org.wildfly.security.auth.realm.IntegrityException invalidIdentitySignature(final String s) {
+ final org.wildfly.security.auth.realm.IntegrityException result = new org.wildfly.security.auth.realm.IntegrityException(String.format(getLoggingLocale(), invalidIdentitySignature$str(), s));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String unableToGenerateSignature$str() {
+ return "ELY13008: Unable to create a signature for the file: %s.";
+ }
+ @Override
+ public final RealmUnavailableException unableToGenerateSignature(final String s) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), unableToGenerateSignature$str(), s));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String cannotFindSignature$str() {
+ return "ELY13009: Unable to locate the signature element for the file: %s";
+ }
+ @Override
+ public final RealmUnavailableException cannotFindSignature(final String s) {
+ final RealmUnavailableException result = new RealmUnavailableException(String.format(getLoggingLocale(), cannotFindSignature$str(), s));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String invalidKeyPairArgument$str() {
+ return "ELY13010: Both PrivateKey and PublicKey must be defined for realm at: %s";
+ }
+ @Override
+ public final IllegalArgumentException invalidKeyPairArgument(final String s) {
+ final IllegalArgumentException result = new IllegalArgumentException(String.format(getLoggingLocale(), invalidKeyPairArgument$str(), s));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ protected String integrityNotEnabled$str() {
+ return "ELY13011: Integrity has not been enabled for the realm at: %s";
+ }
+ @Override
+ public final IllegalArgumentException integrityNotEnabled(final String s) {
+ final IllegalArgumentException result = new IllegalArgumentException(String.format(getLoggingLocale(), integrityNotEnabled$str(), s));
+ _copyStackTraceMinusOne(result);
+ return result;
+ }
+ @Override
+ public final void realmIsNotAvailable(final Exception e) {
+ super.log.logf(FQCN, WARN, e, realmIsNotAvailable$str());
+ }
+ protected String realmIsNotAvailable$str() {
+ return "ELY13012: A realm within the distributed realm is unavailable. This realm will be ignored.";
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FailoverSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FailoverSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FailoverSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,305 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2019 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.realm;
+
+import static org.wildfly.security.auth.realm.ElytronMessages.log;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.Evidence;
+
+import java.security.Principal;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * A realm which wraps one realm and fails over to another in case the first is unavailable.
+ *
+ * @author Martin Mazanek
+ */
+public class FailoverSecurityRealm implements SecurityRealm {
+ protected final SecurityRealm delegateRealm;
+ protected final SecurityRealm failoverRealm;
+ protected final Consumer failoverCallback;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param delegateRealm the wrapped realm
+ * @param failoverRealm the realm to use in case delegateRealm is unavailable
+ * @param failoverCallback callback function that gets called in case delegateRealm is unavailable
+ */
+ public FailoverSecurityRealm(final SecurityRealm delegateRealm, final SecurityRealm failoverRealm, final Consumer failoverCallback) {
+ Assert.checkNotNullParam("delegateRealm", delegateRealm);
+ Assert.checkNotNullParam("failoverRealm", failoverRealm);
+
+ this.delegateRealm = delegateRealm;
+ this.failoverRealm = failoverRealm;
+ this.failoverCallback = failoverCallback;
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Evidence evidence) throws RealmUnavailableException {
+ try {
+ return createFailoverIdentity(delegateRealm.getRealmIdentity(evidence), evidence);
+ } catch (RealmUnavailableException e) {
+ log.realmFailover(e);
+ if (failoverCallback != null) {
+ failoverCallback.accept(e);
+ }
+ return failoverRealm.getRealmIdentity(evidence);
+ }
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Principal principal) throws RealmUnavailableException {
+ try {
+ return createFailoverIdentity(delegateRealm.getRealmIdentity(principal), principal);
+ } catch (RealmUnavailableException e) {
+ log.realmFailover(e);
+ if (failoverCallback != null) {
+ failoverCallback.accept(e);
+ }
+ return failoverRealm.getRealmIdentity(principal);
+ }
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ try {
+ return delegateRealm.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ } catch (RealmUnavailableException rue) {
+ log.realmFailover(rue);
+ if (failoverCallback != null) {
+ failoverCallback.accept(rue);
+ }
+ return SupportLevel.POSSIBLY_SUPPORTED;
+ }
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ try {
+ return delegateRealm.getEvidenceVerifySupport(evidenceType, algorithmName);
+ } catch (RealmUnavailableException rue) {
+ log.realmFailover(rue);
+ if (failoverCallback != null) {
+ failoverCallback.accept(rue);
+ }
+ return SupportLevel.POSSIBLY_SUPPORTED;
+ }
+ }
+
+ protected RealmIdentity createFailoverIdentity(final RealmIdentity identity, final Evidence evidence) {
+ return new FailoverRealmIdentity(identity) {
+ @Override
+ protected RealmIdentity getFailoverIdentity() throws RealmUnavailableException {
+ return failoverRealm.getRealmIdentity(evidence);
+ }
+ };
+ }
+
+ protected RealmIdentity createFailoverIdentity(final RealmIdentity identity, final Principal principal) {
+ return new FailoverRealmIdentity(identity) {
+ @Override
+ protected RealmIdentity getFailoverIdentity() throws RealmUnavailableException {
+ return failoverRealm.getRealmIdentity(principal);
+ }
+ };
+ }
+
+ protected abstract class FailoverRealmIdentity implements RealmIdentity {
+ protected RealmIdentity delegate;
+ protected boolean failed = false;
+
+ public FailoverRealmIdentity(final RealmIdentity identity) {
+ this.delegate = identity;
+ }
+
+ protected abstract RealmIdentity getFailoverIdentity() throws RealmUnavailableException;
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(Class extends Credential> credentialType, String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ try {
+ return delegate.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+ }
+
+ @Override
+ public C getCredential(Class credentialType) throws RealmUnavailableException {
+ try {
+ return delegate.getCredential(credentialType);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getCredential(credentialType);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(Class extends Evidence> evidenceType, String algorithmName) throws RealmUnavailableException {
+ try {
+ return delegate.getEvidenceVerifySupport(evidenceType, algorithmName);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getEvidenceVerifySupport(evidenceType, algorithmName);
+ }
+ }
+
+ @Override
+ public boolean verifyEvidence(Evidence evidence) throws RealmUnavailableException {
+ try {
+ return delegate.verifyEvidence(evidence);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).verifyEvidence(evidence);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public boolean exists() throws RealmUnavailableException {
+ try {
+ return delegate.exists();
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).exists();
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public void updateCredential(Credential credential) throws RealmUnavailableException {
+ try {
+ delegate.updateCredential(credential);
+ } catch (RealmUnavailableException rue) {
+ failover(rue).updateCredential(credential);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public Principal getRealmIdentityPrincipal() {
+ return delegate.getRealmIdentityPrincipal();
+ }
+
+ @Override
+ public C getCredential(Class credentialType, String algorithmName) throws RealmUnavailableException {
+ try {
+ return delegate.getCredential(credentialType, algorithmName);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getCredential(credentialType, algorithmName);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ try {
+ return delegate.getCredential(credentialType, algorithmName, parameterSpec);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getCredential(credentialType, algorithmName, parameterSpec);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public R applyToCredential(Class credentialType, Function function) throws RealmUnavailableException {
+ try {
+ return delegate.applyToCredential(credentialType, function);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).applyToCredential(credentialType, function);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public R applyToCredential(Class credentialType, String algorithmName, Function function) throws RealmUnavailableException {
+ try {
+ return delegate.applyToCredential(credentialType, algorithmName, function);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).applyToCredential(credentialType, algorithmName, function);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public R applyToCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec, final Function function) throws RealmUnavailableException {
+ try {
+ return delegate.applyToCredential(credentialType, algorithmName, parameterSpec, function);
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).applyToCredential(credentialType, algorithmName, parameterSpec, function);
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ delegate.dispose();
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ try {
+ return delegate.getAuthorizationIdentity();
+ } catch (RealmUnavailableException rue) {
+ return failover(rue).getAuthorizationIdentity();
+ } finally {
+ disableFailover();
+ }
+ }
+
+ @Override
+ public Attributes getAttributes() throws RealmUnavailableException {
+ return delegate.getAttributes();
+ }
+
+ protected RealmIdentity failover(RealmUnavailableException rue) throws RealmUnavailableException {
+ if (failed) {
+ throw rue;
+ }
+ log.realmFailover(rue);
+ if (FailoverSecurityRealm.this.failoverCallback != null) {
+ FailoverSecurityRealm.this.failoverCallback.accept(rue);
+ }
+ failed = true;
+ delegate.dispose();
+ delegate = getFailoverIdentity();
+ return delegate;
+ }
+
+ // Used to make sure that failover cannot happen in the middle of authentication.
+ protected void disableFailover() {
+ failed = true;
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemRealmUtil.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemRealmUtil.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemRealmUtil.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2021 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.realm;
+
+
+import java.util.List;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.principal.NamePrincipal;
+import org.wildfly.security.auth.server.ModifiableRealmIdentity;
+import org.wildfly.security.auth.server.ModifiableRealmIdentityIterator;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.credential.Credential;
+
+/**
+ * A utility class to utilize methods from the {@code FileSystemSecurityRealm} class for the Elytron Tool.
+ *
+ * @author Ashpan Raskar
+ * @author Cameron Rodriguez
+ */
+public class FileSystemRealmUtil {
+
+ /**
+ * Copies identities from an existing {@code FileSystemSecurityRealm} to a new one.
+ *
+ * @param oldRealm the existing {@code FileSystemSecurityRealm} with the identities
+ * @param newRealm the new {@code FileSystemSecurityRealm}
+ * @throws RealmUnavailableException if either realm is unavailable or an operation fails
+ */
+ public static void cloneIdentitiesToNewRealm(FileSystemSecurityRealm oldRealm, FileSystemSecurityRealm newRealm) throws RealmUnavailableException {
+ Assert.checkNotNullParam("Old FileSystem Realm", oldRealm);
+ Assert.checkNotNullParam("New FileSystem Realm", newRealm);
+
+ ModifiableRealmIdentityIterator realmIterator = oldRealm.getRealmIdentityIterator();
+
+ while (realmIterator.hasNext()) {
+ ModifiableRealmIdentity oldIdentity = realmIterator.next();
+ List credentials = ((FileSystemSecurityRealm.Identity) oldIdentity).loadCredentials();
+ Attributes attributes = oldIdentity.getAttributes();
+
+ ModifiableRealmIdentity newIdentity = newRealm.getRealmIdentityForUpdate(new NamePrincipal(oldIdentity.getRealmIdentityPrincipal().getName()));
+ newIdentity.create();
+ newIdentity.setCredentials(credentials);
+ newIdentity.setAttributes(attributes);
+ newIdentity.dispose();
+ }
+ realmIterator.close();
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,1696 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2015 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import static java.nio.file.StandardOpenOption.CREATE_NEW;
+import static java.nio.file.StandardOpenOption.DSYNC;
+import static java.nio.file.StandardOpenOption.READ;
+import static java.nio.file.StandardOpenOption.WRITE;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static org.wildfly.security.provider.util.ProviderUtil.INSTALLED_PROVIDERS;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.security.AccessController;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.text.Normalizer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import javax.crypto.SecretKey;
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.SignedInfo;
+import javax.xml.crypto.dsig.Transform;
+import javax.xml.crypto.dsig.XMLSignature;
+import javax.xml.crypto.dsig.XMLSignatureException;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+import javax.xml.crypto.dsig.keyinfo.KeyValue;
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
+import javax.xml.crypto.dsig.spec.TransformParameterSpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.wildfly.common.Assert;
+import org.wildfly.common.bytes.ByteStringBuilder;
+import org.wildfly.common.codec.Base32Alphabet;
+import org.wildfly.common.codec.Base64Alphabet;
+import org.wildfly.common.iteration.ByteIterator;
+import org.wildfly.common.iteration.CodePointIterator;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.auth.principal.NamePrincipal;
+import org.wildfly.security.auth.realm.IdentitySharedExclusiveLock.IdentityLock;
+import org.wildfly.security.auth.server.ModifiableRealmIdentity;
+import org.wildfly.security.auth.server.ModifiableRealmIdentityIterator;
+import org.wildfly.security.auth.server.ModifiableSecurityRealm;
+import org.wildfly.security.auth.server.NameRewriter;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.authz.MapAttributes;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.credential.PasswordCredential;
+import org.wildfly.security.credential.PublicKeyCredential;
+import org.wildfly.security.credential.X509CertificateChainPublicCredential;
+import org.wildfly.security.encryption.CipherUtil;
+import org.wildfly.security.evidence.Evidence;
+import org.wildfly.security.password.Password;
+import org.wildfly.security.password.PasswordFactory;
+import org.wildfly.security.password.interfaces.OneTimePassword;
+import org.wildfly.security.password.spec.BasicPasswordSpecEncoding;
+import org.wildfly.security.password.spec.Encoding;
+import org.wildfly.security.password.spec.OneTimePasswordSpec;
+import org.wildfly.security.password.spec.PasswordSpec;
+import org.wildfly.security.password.util.ModularCrypt;
+import org.wildfly.security.permission.ElytronPermission;
+import org.xml.sax.SAXException;
+
+/**
+ * A simple filesystem-backed security realm.
+ *
+ * @author David M. Lloyd
+ */
+public final class FileSystemSecurityRealm implements ModifiableSecurityRealm, CacheableSecurityRealm {
+
+ static final ElytronPermission CREATE_SECURITY_REALM = ElytronPermission.forName("createSecurityRealm");
+
+ private final Supplier providers;
+ static final Map KNOWN_NAMESPACES;
+
+ private enum Version {
+
+ VERSION_1_0("urn:elytron:1.0", null),
+ VERSION_1_0_1("urn:elytron:1.0.1", VERSION_1_0),
+ VERSION_1_1("urn:elytron:identity:1.1", VERSION_1_0_1),
+ VERSION_1_2("urn:elytron:identity:1.2", VERSION_1_1);
+
+ final String namespace;
+
+ /*
+ * In the future we could support multiple parents but wait until that becomes a reality before adding it.
+ */
+ final Version parent;
+
+ Version(String namespace, Version parent) {
+ this.namespace = namespace;
+ this.parent = parent;
+ }
+
+ String getNamespace() {
+ return namespace;
+ }
+
+ boolean isAtLeast(Version version) {
+ return this.equals(version) || (parent != null ? parent.isAtLeast(version) : false);
+ }
+
+ }
+
+ static {
+ Map knownNamespaces = new HashMap<>();
+ for (Version version : Version.values()) {
+ knownNamespaces.put(version.namespace, version);
+ }
+ KNOWN_NAMESPACES = Collections.unmodifiableMap(knownNamespaces);
+ }
+
+ private final Path root;
+ private final NameRewriter nameRewriter;
+ private final int levels;
+ private final boolean encoded;
+ private final Charset hashCharset;
+ private final Encoding hashEncoding;
+ private final SecretKey secretKey;
+ private final PrivateKey privateKey;
+ private final PublicKey publicKey;
+ private final ConcurrentHashMap realmIdentityLocks = new ConcurrentHashMap<>();
+
+ /**
+ * Construct a new instance of the FileSystemSecurityRealmBuilder.
+ *
+ * @return the new FileSystemSecurityRealmBuilder instance
+ */
+ public static FileSystemSecurityRealmBuilder builder() {
+ return new FileSystemSecurityRealmBuilder();
+ }
+ /**
+ * Construct a new instance.
+ *
+ * Construction with enabled security manager requires {@code createSecurityRealm} {@link ElytronPermission}.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ * @param encoded whether identity names should be BASE32 encoded before using as filename (only applies if the security realm is unencrypted)
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default.
+ * @param hashEncoding the string format for the hashed passwords. Uses Base64 by default.
+ * @param providers The providers supplier
+ * @param secretKey the SecretKey used to encrypt and decrypt the security realm (if {@code null}, the security realm will be unencrypted)
+ * @param privateKey the PrivateKey used to verify the integrity of the security realm (if {@code null}, the security realm will not verify integrity)
+ * @param publicKey the PublicKey used to verify the integrity of the security realm (if {@code null}, the security realm will not verify integrity)
+ *
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels, final boolean encoded, final Encoding hashEncoding, final Charset hashCharset, final Supplier providers, final SecretKey secretKey, final PrivateKey privateKey, final PublicKey publicKey) {
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(CREATE_SECURITY_REALM);
+ }
+ this.root = root;
+ this.nameRewriter = nameRewriter;
+ this.levels = levels;
+ this.encoded = secretKey == null && encoded;
+ this.hashCharset = hashCharset != null ? hashCharset : StandardCharsets.UTF_8;
+ this.hashEncoding = hashEncoding != null ? hashEncoding : Encoding.BASE64;
+ this.providers = providers != null ? providers : INSTALLED_PROVIDERS;
+ this.secretKey = secretKey;
+ this.privateKey = privateKey;
+ this.publicKey = publicKey;
+
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * Construction with enabled security manager requires {@code createSecurityRealm} {@link ElytronPermission}.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ * @param encoded whether identity names should be BASE32 encoded before using as filename
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default.
+ * @param hashEncoding the string format for the hashed passwords. Uses Base64 by default.
+ * @param secretKey the SecretKey used to encrypt and decrypt the security realm (if {@code null}, the security realm will be unencrypted)
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels, final boolean encoded, final Encoding hashEncoding, final Charset hashCharset, final SecretKey secretKey) {
+ this(root, nameRewriter, levels, encoded, hashEncoding, hashCharset, INSTALLED_PROVIDERS, secretKey, null, null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * Construction with enabled security manager requires {@code createSecurityRealm} {@link ElytronPermission}.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ * @param encoded whether identity names should be BASE32 encoded before using as filename
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default.
+ * @param hashEncoding the string format for the hashed passwords. Uses Base64 by default.
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels, final boolean encoded, final Encoding hashEncoding, final Charset hashCharset) {
+ this(root, nameRewriter, levels, encoded, hashEncoding, hashCharset, INSTALLED_PROVIDERS, null, null, null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * Construction with enabled security manager requires {@code createSecurityRealm} {@link ElytronPermission}.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ * @param encoded whether identity names should by BASE32 encoded before using as filename
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels, final boolean encoded) {
+ this(root, nameRewriter, levels, encoded, Encoding.BASE64, StandardCharsets.UTF_8, INSTALLED_PROVIDERS, null, null, null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels) {
+ this(root, nameRewriter, levels, true);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param root the root path of the identity store
+ * @param nameRewriter the name rewriter to apply to looked up names
+ * @param levels the number of levels of directory hashing to apply
+ * @param hashEncoding the string format for hashed passwords. Uses Base64 by default.
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default and must not be {@code null}.
+ */
+ public FileSystemSecurityRealm(final Path root, final NameRewriter nameRewriter, final int levels, final Encoding hashEncoding, final Charset hashCharset) {
+ this(root, nameRewriter, levels, true, hashEncoding, hashCharset, INSTALLED_PROVIDERS, null, null, null);
+ }
+
+
+
+ /**
+ * Construct a new instance.
+ *
+ * @param root the root path of the identity store
+ * @param levels the number of levels of directory hashing to apply
+ */
+ public FileSystemSecurityRealm(final Path root, final int levels) {
+ this(root, NameRewriter.IDENTITY_REWRITER, levels, true);
+ }
+
+
+ /**
+ * Construct a new instance.
+ *
+ * @param root the root path of the identity store
+ * @param levels the number of levels of directory hashing to apply
+ * @param hashEncoding the string format for hashed passwords. Uses Base64 by default.
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default and must not be {@code null}.
+ */
+ public FileSystemSecurityRealm(final Path root, final int levels, final Encoding hashEncoding, final Charset hashCharset) {
+ this(root, NameRewriter.IDENTITY_REWRITER, levels, true, hashEncoding, hashCharset, INSTALLED_PROVIDERS, null, null, null);
+ }
+
+ /**
+ * Construct a new instance with 2 levels of hashing.
+ *
+ * @param root the root path of the identity store
+ */
+ public FileSystemSecurityRealm(final Path root) {
+ this(root, NameRewriter.IDENTITY_REWRITER, 2, true);
+ }
+
+ /**
+ * Construct a new instance with 2 levels of hashing.
+ *
+ * @param root the root path of the identity store
+ * @param hashEncoding the string format for hashed passwords. Uses Base64 by default.
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default and must not be {@code null}
+ */
+ public FileSystemSecurityRealm(final Path root, final Encoding hashEncoding, final Charset hashCharset) {
+ this(root, NameRewriter.IDENTITY_REWRITER, 2, true, hashEncoding, hashCharset, INSTALLED_PROVIDERS, null, null, null);
+ }
+
+ public FileSystemSecurityRealm(Path root, int levels, Supplier providers) {
+ this(root, NameRewriter.IDENTITY_REWRITER, levels, true, Encoding.BASE64, StandardCharsets.UTF_8, providers, null, null, null);
+ }
+
+ /**
+ * Checks if the FileSystemSecurityRealm has Integrity checking enabled
+ * @return {@code true} if Integrity checking is enabled, and {@code false} otherwise
+ */
+ public boolean hasIntegrityEnabled() {
+ return privateKey != null && publicKey != null;
+ }
+ private Path pathFor(String name) {
+ assert name.codePointCount(0, name.length()) > 0;
+ String normalizedName = name;
+
+ if (encoded) {
+ normalizedName = Normalizer.normalize(name, Normalizer.Form.NFKC)
+ .toLowerCase(Locale.ROOT)
+ .replaceAll("[^a-z0-9]", "_");
+ }
+ if (secretKey != null || encoded) {
+ String base32 = ByteIterator.ofBytes(new ByteStringBuilder().append(name).toArray())
+ .base32Encode(Base32Alphabet.STANDARD, false).drainToString();
+ normalizedName = secretKey != null ? base32 : normalizedName + "-" + base32;
+ }
+
+ Path path = root;
+ int idx = 0;
+ for (int level = 0; level < levels; level ++) {
+ int newIdx = normalizedName.offsetByCodePoints(idx, 1);
+ path = path.resolve(normalizedName.substring(idx, newIdx));
+ idx = newIdx;
+ if (idx == normalizedName.length()) {
+ break;
+ }
+ }
+
+ return path.resolve(normalizedName + ".xml");
+ }
+
+ public Charset getHashCharset() {
+ return this.hashCharset;
+ }
+
+ private String nameFor(Path path) {
+ String fileName = path.toString();
+ fileName = fileName.substring(0, fileName.length() - 4); // remove ".xml"
+
+ if (secretKey != null) {
+ CodePointIterator it = CodePointIterator.ofString(fileName);
+ fileName = it.base32Decode(Base32Alphabet.STANDARD, false)
+ .asUtf8String().drainToString();
+ } else if (encoded) {
+ CodePointIterator it = CodePointIterator.ofString(fileName);
+ it.delimitedBy('-').skipAll();
+ it.next(); // skip '-'
+ fileName = it.base32Decode(Base32Alphabet.STANDARD, false)
+ .asUtf8String().drainToString();
+ }
+ return fileName;
+ }
+
+ public RealmIdentity getRealmIdentity(final Principal principal) {
+ return NamePrincipal.isConvertibleTo(principal) ? getRealmIdentity(principal.getName(), false) : RealmIdentity.NON_EXISTENT;
+ }
+
+ @Override
+ public ModifiableRealmIdentity getRealmIdentityForUpdate(final Principal principal) {
+ return NamePrincipal.isConvertibleTo(principal) ? getRealmIdentity(principal.getName(), true) : ModifiableRealmIdentity.NON_EXISTENT;
+ }
+
+ @Override
+ public void registerIdentityChangeListener(Consumer listener) {
+ // no need to register the listener given that changes to identities are done through the realm
+ }
+
+ private ModifiableRealmIdentity getRealmIdentity(final String name, final boolean exclusive) {
+ final String finalName = nameRewriter.rewriteName(name);
+ if (finalName == null) {
+ throw ElytronMessages.log.invalidName();
+ }
+
+ // Acquire the appropriate lock for the realm identity
+ IdentitySharedExclusiveLock realmIdentityLock = getRealmIdentityLockForName(finalName);
+ IdentityLock lock;
+ if (exclusive) {
+ lock = realmIdentityLock.lockExclusive();
+ } else {
+ lock = realmIdentityLock.lockShared();
+ }
+ return new Identity(finalName, pathFor(finalName), lock, hashCharset, hashEncoding, providers, secretKey, privateKey, publicKey, hasIntegrityEnabled());
+ }
+
+ @Override
+ public ModifiableRealmIdentityIterator getRealmIdentityIterator() throws RealmUnavailableException {
+ return subIterator(root, levels);
+ }
+
+ private ModifiableRealmIdentityIterator subIterator(final Path root, final int levels) {
+ final DirectoryStream stream;
+ final Iterator iterator;
+ if (levels == 0) {
+ try {
+ stream = Files.newDirectoryStream(root, "*.xml");
+ iterator = stream.iterator();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to open directory", e);
+ return ModifiableRealmIdentityIterator.emptyIterator();
+ }
+ return new ModifiableRealmIdentityIterator() {
+
+ public boolean hasNext() {
+ if ( ! iterator.hasNext()) {
+ try {
+ close();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to close the stream", e);
+ }
+ }
+ return iterator.hasNext();
+ }
+
+ public ModifiableRealmIdentity next() {
+ final Path path = iterator.next();
+ final String name = nameFor(path.getFileName());
+ return getRealmIdentityForUpdate(new NamePrincipal(name));
+ }
+
+ public void close() throws RealmUnavailableException {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to close the stream", e);
+ }
+ }
+ };
+ } else {
+ try {
+ stream = Files.newDirectoryStream(root, entry -> {
+ final String fileName = entry.getFileName().toString();
+ return fileName.length() == 1 && !fileName.equals(".") && Files.isDirectory(entry);
+ });
+ iterator = stream.iterator();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to open directory", e);
+ return ModifiableRealmIdentityIterator.emptyIterator();
+ }
+ return new ModifiableRealmIdentityIterator() {
+ private ModifiableRealmIdentityIterator subIterator;
+
+ public boolean hasNext() {
+ for (;;) {
+ if (subIterator == null) {
+ if (! iterator.hasNext()) {
+ try {
+ close();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to close the stream", e);
+ }
+ return false;
+ }
+ final Path path = iterator.next();
+ subIterator = subIterator(path, levels - 1);
+ } else if (subIterator.hasNext()) {
+ return true;
+ } else {
+ subIterator = null;
+ }
+ }
+ }
+
+ public ModifiableRealmIdentity next() {
+ if (! hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return subIterator.next();
+ }
+
+ public void close() throws RealmUnavailableException {
+ try {
+ if (subIterator != null) subIterator.close();
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ ElytronMessages.log.debug("Unable to close the stream", e);
+ }
+ }
+ }
+ };
+ }
+ }
+
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return SupportLevel.POSSIBLY_SUPPORTED;
+ }
+
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ return SupportLevel.POSSIBLY_SUPPORTED;
+ }
+
+ private IdentitySharedExclusiveLock getRealmIdentityLockForName(final String name) {
+ IdentitySharedExclusiveLock realmIdentityLock = realmIdentityLocks.get(name);
+ if (realmIdentityLock == null) {
+ final IdentitySharedExclusiveLock newRealmIdentityLock = new IdentitySharedExclusiveLock();
+ realmIdentityLock = realmIdentityLocks.putIfAbsent(name, newRealmIdentityLock);
+ if (realmIdentityLock == null) {
+ realmIdentityLock = newRealmIdentityLock;
+ }
+ }
+ return realmIdentityLock;
+ }
+
+ @FunctionalInterface
+ interface CredentialParseFunction {
+ void parseCredential(String algorithm, String format, String body) throws RealmUnavailableException, XMLStreamException;
+ }
+
+ /**
+ * Re-generate the signatures for all the identities in this realm.
+ * This method is intended to be called after updating the key pair used by this realm.
+ *
+ * @throws RealmUnavailableException if the realm is not able to handle requests for any reason
+ */
+ public void updateRealmKeyPair() throws RealmUnavailableException {
+ if (! hasIntegrityEnabled()) {
+ throw ElytronMessages.log.integrityNotEnabled(root.toString());
+ }
+ ModifiableRealmIdentityIterator realmIterator = this.getRealmIdentityIterator();
+ while (realmIterator.hasNext()) {
+ Identity identity = (Identity) realmIterator.next();
+ try{
+ identity.writeDigitalSignature(identity.path, identity.name);
+ } finally {
+ identity.dispose();
+ }
+ }
+ realmIterator.close();
+ }
+
+ /**
+ * Verify the integrity of each identity file in this realm.
+ * @return {@code true} if the integrity of all the identity files in the realm is successfully verified and {@code false} otherwise
+ *
+ */
+ public IntegrityResult verifyRealmIntegrity() throws RealmUnavailableException {
+ if (! hasIntegrityEnabled()) {
+ throw ElytronMessages.log.integrityNotEnabled(root.toString());
+ }
+ ArrayList failedIdentities = new ArrayList<>();
+ ModifiableRealmIdentityIterator realmIterator = this.getRealmIdentityIterator();
+ while (realmIterator.hasNext()) {
+ Identity identity = (Identity) realmIterator.next();
+ if(! identity.isIntegrityValid()) {
+ failedIdentities.add(identity.name);
+ }
+ identity.dispose();
+ }
+ realmIterator.close();
+ return new IntegrityResult(failedIdentities.isEmpty(), failedIdentities);
+ }
+
+ static class Identity implements ModifiableRealmIdentity {
+
+ private static final String ENCRYPTION_FORMAT = "enc_base64";
+ private static final String BASE64_FORMAT = "base64";
+ private static final String MCF_FORMAT = "crypt";
+ private static final String X509_FORMAT = "X.509";
+ private static final String HEX = "hex";
+
+ private final String name;
+ private final Path path;
+ private final Supplier providers;
+ private IdentityLock lock;
+ private final Charset hashCharset;
+ private final Encoding hashEncoding;
+ private final SecretKey secretKey;
+ private final PrivateKey privateKey;
+ private final PublicKey publicKey;
+ private final boolean integrityEnabled;
+
+ Identity(final String name, final Path path, final IdentityLock lock, final Charset hashCharset, final Encoding hashEncoding, Supplier providers, final SecretKey secretKey, final PrivateKey privateKey, final PublicKey publicKey, final boolean integrityEnabled) {
+ this.name = name;
+ this.path = path;
+ this.lock = lock;
+ this.hashCharset = hashCharset;
+ this.hashEncoding = hashEncoding;
+ this.providers = providers;
+ this.secretKey = secretKey;
+ this.privateKey = privateKey;
+ this.publicKey = publicKey;
+ this.integrityEnabled = integrityEnabled;
+ }
+
+ public Principal getRealmIdentityPrincipal() {
+ return new NamePrincipal(name);
+ }
+
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ List credentials = loadCredentials();
+ for (Credential credential : credentials) {
+ if (credential.matches(credentialType, algorithmName, parameterSpec)) {
+ return SupportLevel.SUPPORTED;
+ }
+ }
+ return SupportLevel.UNSUPPORTED;
+ }
+
+ @Override
+ public C getCredential(final Class credentialType) throws RealmUnavailableException {
+ return getCredential(credentialType, null);
+ }
+
+ public C getCredential(final Class credentialType, final String algorithmName) throws RealmUnavailableException {
+ return getCredential(credentialType, algorithmName, null);
+ }
+
+ public C getCredential(final Class credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ List credentials = loadCredentials();
+ for (Credential credential : credentials) {
+ if (credential.matches(credentialType, algorithmName, parameterSpec)) {
+ return credentialType.cast(credential.clone());
+ }
+ }
+ return null;
+ }
+
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ Assert.checkNotNullParam("evidenceType", evidenceType);
+ List credentials = loadCredentials();
+ for (Credential credential : credentials) {
+ if (credential.canVerify(evidenceType, algorithmName)) {
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - evidence verification SUPPORTED: type = [%s] algorithm = [%s] credentials = [%d]", evidenceType, algorithmName, credentials.size());
+ return SupportLevel.SUPPORTED;
+ }
+ }
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - evidence verification UNSUPPORTED: type = [%s] algorithm = [%s] credentials = [%d]", evidenceType, algorithmName, credentials.size());
+ return SupportLevel.UNSUPPORTED;
+ }
+
+ public boolean verifyEvidence(final Evidence evidence) throws RealmUnavailableException {
+ Assert.checkNotNullParam("evidence", evidence);
+
+ if (ElytronMessages.log.isTraceEnabled()) {
+ try {
+ final LoadedIdentity loadedIdentity = loadIdentity(false, true);
+ ElytronMessages.log.tracef("Trying to authenticate identity %s using FileSystemSecurityRealm", (loadedIdentity != null) ? loadedIdentity.getName() : "null");
+ } catch (RealmUnavailableException e) {
+ if (e.getCause() instanceof IntegrityException) {
+ return false;
+ }
+ throw e;
+ }
+ }
+ List credentials = null;
+ try {
+ credentials = loadCredentials();
+ } catch (RealmUnavailableException e) {
+ if (e.getCause() instanceof IntegrityException) {
+ return false;
+ }
+ throw e;
+ }
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification evidence [%s] against [%d] credentials...", evidence, credentials.size());
+ for (Credential credential : credentials) {
+ if (credential.canVerify(evidence)) {
+ boolean verified = false;
+ if (credential instanceof PasswordCredential) {
+ verified = ((PasswordCredential )credential).verify(providers, evidence, hashCharset);
+ } else {
+ verified = credential.verify(providers, evidence);
+ }
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification against credential [%s] = %b", credential, verified);
+ return verified;
+ }
+ }
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - no credential able to verify evidence [%s]", evidence);
+ return false;
+ }
+
+ List loadCredentials() throws RealmUnavailableException {
+ final LoadedIdentity loadedIdentity = loadIdentity(false, true);
+ return loadedIdentity == null ? Collections.emptyList() : loadedIdentity.getCredentials();
+ }
+
+ public boolean exists() throws RealmUnavailableException {
+ if (System.getSecurityManager() == null) {
+ return Files.exists(path);
+ }
+ return AccessController.doPrivileged((PrivilegedAction) () -> Files.exists(path));
+ }
+
+ public void delete() throws RealmUnavailableException {
+ if (System.getSecurityManager() == null) {
+ deletePrivileged();
+ return;
+ }
+ try {
+ AccessController.doPrivileged((PrivilegedExceptionAction) this::deletePrivileged);
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof RealmUnavailableException) {
+ throw (RealmUnavailableException) e.getException();
+ }
+ throw new RuntimeException(e.getException());
+ }
+ }
+
+ private Void deletePrivileged() throws RealmUnavailableException {
+ try {
+ Files.delete(path);
+ return null;
+ } catch (NoSuchFileException e) {
+ throw ElytronMessages.log.fileSystemRealmNotFound(name);
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemRealmDeleteFailed(name, e);
+ }
+ }
+
+ private String tempSuffix() {
+ final ThreadLocalRandom random = ThreadLocalRandom.current();
+ char[] array = new char[12];
+ for (int i = 0; i < array.length; i ++) {
+ int idx = random.nextInt(36);
+ if (idx < 26) {
+ array[i] = (char) ('A' + idx);
+ } else {
+ array[i] = (char) ('0' + idx - 26);
+ }
+ }
+ return new String(array);
+ }
+
+ private Path tempPath() {
+ Path parent = path.getParent();
+ File file = parent.toFile();
+ if (!file.exists()) {
+ file.mkdirs();
+ }
+ return parent.resolve(path.getFileName().toString() + '.' + tempSuffix());
+ }
+
+ public void create() throws RealmUnavailableException {
+ if (System.getSecurityManager() == null) {
+ createPrivileged();
+ return;
+ }
+ try {
+ AccessController.doPrivileged((PrivilegedExceptionAction) this::createPrivileged);
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof RealmUnavailableException) {
+ throw (RealmUnavailableException) e.getException();
+ }
+ throw new RuntimeException(e.getException());
+ }
+ }
+
+ private Void createPrivileged() throws RealmUnavailableException {
+ for (;;) {
+ final Path tempPath = tempPath();
+ final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
+ try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(tempPath, WRITE, CREATE_NEW, DSYNC))) {
+ try (AutoCloseableXMLStreamWriterHolder holder = new AutoCloseableXMLStreamWriterHolder(xmlOutputFactory.createXMLStreamWriter(outputStream))) {
+ String namespace = "";
+ if (integrityEnabled) {
+ namespace = Version.VERSION_1_2.getNamespace();
+ } else if (secretKey != null) {
+ namespace = Version.VERSION_1_1.getNamespace();
+ } else {
+ namespace = Version.VERSION_1_0.getNamespace();
+ }
+ final XMLStreamWriter streamWriter = holder.getXmlStreamWriter();
+ // create empty identity
+ streamWriter.writeStartDocument();
+ streamWriter.writeCharacters("\n");
+ streamWriter.writeStartElement("identity");
+ streamWriter.writeDefaultNamespace(namespace);
+ if (integrityEnabled) {
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeStartElement("principal");
+ streamWriter.writeAttribute("name", secretKey != null ? CipherUtil.encrypt(name, secretKey) : name);
+ streamWriter.writeEndElement();
+ streamWriter.writeCharacters("\n ");
+ }
+ streamWriter.writeEndElement();
+ streamWriter.writeEndDocument();
+ } catch (XMLStreamException | GeneralSecurityException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToWrite(tempPath, name, e);
+ }
+ if(integrityEnabled) {
+ try {
+ writeDigitalSignature(tempPath, this.name);
+ } catch (RealmUnavailableException e) {
+ throw ElytronMessages.log.unableToGenerateSignature(path.toString());
+ }
+ }
+ } catch (FileAlreadyExistsException ignored) {
+ // try a new name
+ continue;
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToOpen(tempPath, name, e);
+ }
+ try {
+ Files.createLink(path, tempPath);
+ } catch (FileAlreadyExistsException e) {
+ try {
+ Files.delete(tempPath);
+ } catch (IOException e2) {
+ e.addSuppressed(e2);
+ }
+ throw ElytronMessages.log.fileSystemRealmAlreadyExists(name, e);
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToWrite(tempPath, name, e);
+ }
+ try {
+ Files.delete(tempPath);
+ } catch (IOException ignored) {
+ // nothing we can do
+ }
+ return null;
+ }
+ }
+
+ public void setCredentials(final Collection extends Credential> credentials) throws RealmUnavailableException {
+ Assert.checkNotNullParam("credential", credentials);
+ final LoadedIdentity loadedIdentity = loadIdentity(false, false);
+ if (loadedIdentity == null) {
+ throw ElytronMessages.log.fileSystemRealmNotFound(name);
+ }
+
+ final LoadedIdentity newIdentity = new LoadedIdentity(name, new ArrayList<>(credentials), loadedIdentity.getAttributes(), hashEncoding);
+ replaceIdentity(newIdentity);
+ }
+
+ public void setAttributes(final Attributes attributes) throws RealmUnavailableException {
+ Assert.checkNotNullParam("attributes", attributes);
+ final LoadedIdentity loadedIdentity = loadIdentity(false, true);
+ if (loadedIdentity == null) {
+ throw ElytronMessages.log.fileSystemRealmNotFound(name);
+ }
+ final LoadedIdentity newIdentity = new LoadedIdentity(name, loadedIdentity.getCredentials(), attributes, hashEncoding);
+ replaceIdentity(newIdentity);
+ }
+
+ @Override
+ public Attributes getAttributes() throws RealmUnavailableException {
+ final LoadedIdentity loadedIdentity = loadIdentity(true, false);
+ if (loadedIdentity == null) {
+ throw ElytronMessages.log.fileSystemRealmNotFound(name);
+ }
+ return loadedIdentity.getAttributes().asReadOnly();
+ }
+
+ private void replaceIdentity(final LoadedIdentity newIdentity) throws RealmUnavailableException {
+ if (System.getSecurityManager() == null) {
+ replaceIdentityPrivileged(newIdentity);
+ return;
+ }
+ try {
+ AccessController.doPrivileged((PrivilegedExceptionAction) () -> replaceIdentityPrivileged(newIdentity));
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof RealmUnavailableException) {
+ throw (RealmUnavailableException) e.getException();
+ }
+ throw new RuntimeException(e.getException());
+ }
+ }
+
+ private Void replaceIdentityPrivileged(final LoadedIdentity newIdentity) throws RealmUnavailableException {
+ if (!isIntegrityValid()) {
+ throw new RealmUnavailableException(ElytronMessages.log.invalidIdentitySignature(name));
+ }
+ for (;;) {
+ final Path tempPath = tempPath();
+ try {
+ final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
+ try (OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(tempPath, WRITE, CREATE_NEW, DSYNC))) {
+ try (AutoCloseableXMLStreamWriterHolder holder = new AutoCloseableXMLStreamWriterHolder(xmlOutputFactory.createXMLStreamWriter(outputStream))) {
+ writeIdentity(holder.getXmlStreamWriter(), newIdentity);
+ } catch (XMLStreamException | InvalidKeySpecException | NoSuchAlgorithmException | CertificateEncodingException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToWrite(tempPath, name, e);
+ } catch (GeneralSecurityException e) {
+ throw ElytronMessages.log.fileSystemRealmEncryptionFailed(e);
+ }
+ if (integrityEnabled) {
+ try {
+ writeDigitalSignature(tempPath, name);
+ } catch (RealmUnavailableException e) {
+ throw ElytronMessages.log.unableToGenerateSignature(path.toString());
+ }
+ }
+ } catch (FileAlreadyExistsException ignored) {
+ // try a new name
+ continue;
+ } catch (IOException e) {
+ try {
+ Files.deleteIfExists(tempPath);
+ } catch (IOException e2) {
+ e.addSuppressed(e2);
+ }
+ throw ElytronMessages.log.fileSystemRealmFailedToOpen(tempPath, name, e);
+ }
+ try {
+ Files.delete(path);
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemUpdatedFailed(path.toAbsolutePath().toString(), e);
+ }
+ try {
+ Files.createLink(path, tempPath);
+ } catch (FileAlreadyExistsException e) {
+ try {
+ Files.deleteIfExists(tempPath);
+ } catch (IOException e2) {
+ e.addSuppressed(e2);
+ }
+ throw ElytronMessages.log.fileSystemRealmAlreadyExists(name, e);
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToWrite(tempPath, name, e);
+ }
+ try {
+ Files.delete(tempPath);
+ } catch (IOException ignored) {
+ // nothing we can do
+ }
+ return null;
+ } catch (Throwable t) {
+ try {
+ Files.delete(tempPath);
+ } catch (IOException e) {
+ t.addSuppressed(e);
+ }
+ throw t;
+ }
+ }
+ }
+
+ private Version requiredVersion(final LoadedIdentity identityToWrite) {
+ // As new functionality is added we will identify if we need to use a later version
+ // if new functionality is used then use the required schema version otherwise fallback
+ // to an older version.
+
+ if (integrityEnabled) {
+ return Version.VERSION_1_2;
+ } else if (secretKey != null) {
+ return Version.VERSION_1_1;
+ } else {
+ return Version.VERSION_1_0;
+ }
+ }
+
+ private void writeIdentity(final XMLStreamWriter streamWriter, final LoadedIdentity newIdentity) throws XMLStreamException, InvalidKeySpecException, NoSuchAlgorithmException, GeneralSecurityException {
+ streamWriter.writeStartDocument();
+ streamWriter.writeCharacters("\n");
+ streamWriter.writeStartElement("identity");
+ streamWriter.writeDefaultNamespace(requiredVersion(newIdentity).getNamespace());
+
+ if (integrityEnabled) {
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeStartElement("principal");
+ streamWriter.writeAttribute("name", secretKey != null ? CipherUtil.encrypt(name, secretKey) : name);
+ streamWriter.writeEndElement();
+ }
+
+ if (newIdentity.getCredentials().size() > 0) {
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeStartElement("credentials");
+ for (Credential credential : newIdentity.getCredentials()) {
+ streamWriter.writeCharacters("\n ");
+ if (credential instanceof PasswordCredential) {
+ Password password = ((PasswordCredential) credential).getPassword();
+ if (password instanceof OneTimePassword) {
+ final OneTimePassword otp = (OneTimePassword) password;
+ streamWriter.writeStartElement("otp");
+ streamWriter.writeAttribute("algorithm", otp.getAlgorithm());
+ streamWriter.writeAttribute("hash", ByteIterator.ofBytes(otp.getHash()).base64Encode().drainToString());
+ streamWriter.writeAttribute("seed", ByteIterator.ofBytes(otp.getSeed().getBytes(StandardCharsets.US_ASCII)).base64Encode().drainToString());
+ streamWriter.writeAttribute("sequence", Integer.toString(otp.getSequenceNumber()));
+ streamWriter.writeEndElement();
+ } else {
+ streamWriter.writeStartElement("password");
+ String format;
+ String algorithm = password.getAlgorithm();
+ String passwordString;
+ byte[] encoded = BasicPasswordSpecEncoding.encode(password, providers);
+
+ if (secretKey != null) {
+ format = ENCRYPTION_FORMAT;
+ passwordString = ByteIterator.ofBytes(CipherUtil.encrypt(encoded, secretKey)).base64Encode().drainToString();
+ } else if (encoded != null) {
+ if (newIdentity.getHashEncoding() == Encoding.HEX) {
+ format = HEX;
+ passwordString = ByteIterator.ofBytes(encoded).hexEncode().drainToString();
+ } else {
+ // default to base64
+ format = BASE64_FORMAT;
+ passwordString = ByteIterator.ofBytes(encoded).base64Encode().drainToString();
+ }
+ } else {
+ format = MCF_FORMAT;
+ passwordString = ModularCrypt.encodeAsString(password);
+ }
+
+ streamWriter.writeAttribute("algorithm", algorithm);
+ streamWriter.writeAttribute("format", format);
+ streamWriter.writeCharacters(passwordString);
+ streamWriter.writeEndElement();
+ }
+ }
+ }
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeEndElement();
+ }
+ final Iterator entryIter = newIdentity.getAttributes().entries().iterator();
+ if (entryIter.hasNext()) {
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeStartElement("attributes");
+ do {
+ final Attributes.Entry entry = entryIter.next();
+ for (String value : entry) {
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeStartElement("attribute");
+ streamWriter.writeAttribute("name", secretKey != null ? CipherUtil.encrypt(entry.getKey(), secretKey) : entry.getKey());
+ streamWriter.writeAttribute("value", secretKey != null ? CipherUtil.encrypt(value, secretKey) : value);
+ streamWriter.writeEndElement();
+ }
+ } while (entryIter.hasNext());
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeEndElement();
+ streamWriter.writeCharacters("\n");
+ }
+ streamWriter.writeCharacters("\n ");
+ streamWriter.writeEndElement();
+ streamWriter.writeEndDocument();
+ }
+
+ public void dispose() {
+ // Release the lock for this realm identity
+ IdentityLock identityLock = lock;
+ lock = null;
+ if (identityLock != null) {
+ identityLock.release();
+ }
+ }
+
+ @Override
+ public AuthorizationIdentity getAuthorizationIdentity() throws RealmUnavailableException {
+ final LoadedIdentity loadedIdentity = loadIdentity(true, false);
+ return loadedIdentity == null ? AuthorizationIdentity.EMPTY : AuthorizationIdentity.basicIdentity(loadedIdentity.getAttributes());
+ }
+
+ private LoadedIdentity loadIdentity(final boolean skipCredentials, final boolean skipAttributes) throws RealmUnavailableException {
+ if (System.getSecurityManager() == null) {
+ return loadIdentityPrivileged(skipCredentials, skipAttributes);
+ }
+ try {
+ return AccessController.doPrivileged((PrivilegedExceptionAction) () -> loadIdentityPrivileged(skipCredentials, skipAttributes));
+ } catch (PrivilegedActionException e) {
+ if (e.getException() instanceof RealmUnavailableException) {
+ throw (RealmUnavailableException) e.getException();
+ }
+ throw new RuntimeException(e.getException());
+ }
+ }
+
+ protected LoadedIdentity loadIdentityPrivileged(final boolean skipCredentials, final boolean skipAttributes) throws RealmUnavailableException {
+ if (!isIntegrityValid()) {
+ throw new RealmUnavailableException(ElytronMessages.log.invalidIdentitySignature(name));
+ }
+ try (InputStream inputStream = Files.newInputStream(path, READ)) {
+ final XMLInputFactory inputFactory = XMLInputFactory.newFactory();
+ inputFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
+ inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+ inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
+ inputFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
+ try (final AutoCloseableXMLStreamReaderHolder holder = new AutoCloseableXMLStreamReaderHolder(inputFactory.createXMLStreamReader(inputStream, "UTF-8"))) {
+ final XMLStreamReader streamReader = holder.getXmlStreamReader();
+ return parseIdentity(streamReader, skipCredentials, skipAttributes);
+ } catch (XMLStreamException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToRead(path, name, e);
+ }
+ } catch (NoSuchFileException | FileNotFoundException ignored) {
+ return null;
+ } catch (IOException e) {
+ throw ElytronMessages.log.fileSystemRealmFailedToOpen(path, name, e);
+ }
+ }
+
+ private LoadedIdentity parseIdentity(final XMLStreamReader streamReader, final boolean skipCredentials, final boolean skipAttributes) throws RealmUnavailableException, XMLStreamException {
+ final int tag = streamReader.nextTag();
+ Version version;
+ if (tag != START_ELEMENT || ((version = identifyVersion(streamReader)) == null) || ! "identity".equals(streamReader.getLocalName())) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ return parseIdentityContents(streamReader, version, skipCredentials, skipAttributes);
+ }
+
+ private Version identifyVersion(final XMLStreamReader streamReader) {
+ return KNOWN_NAMESPACES.get(streamReader.getNamespaceURI());
+ }
+
+ private LoadedIdentity parseIdentityContents(final XMLStreamReader streamReader, final Version version, final boolean skipCredentials, final boolean skipAttributes) throws RealmUnavailableException, XMLStreamException {
+ final int attributeCount = streamReader.getAttributeCount();
+ if (attributeCount > 0) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ List credentials = Collections.emptyList();
+ Attributes attributes = Attributes.EMPTY;
+ boolean gotCredentials = false;
+ boolean gotAttributes = false;
+ for (;;) {
+ if (streamReader.isEndElement()) {
+ if (attributes == Attributes.EMPTY && !skipAttributes) {
+ // Since this could be a use-case wanting to modify the attributes, make sure that we have a
+ // modifiable version of Attributes;
+ attributes = new MapAttributes();
+ }
+ return new LoadedIdentity(name, credentials, attributes, hashEncoding);
+ }
+ if (!(version.getNamespace().equals(streamReader.getNamespaceURI())) && !(XMLSignature.XMLNS.equals(streamReader.getNamespaceURI()))) {
+ // Mixed versions unsupported.
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+
+ if ("principal".equals(streamReader.getLocalName())) {
+ if (version.isAtLeast(Version.VERSION_1_2)) {
+ consumeContent(streamReader);
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ }
+
+ if (! gotCredentials && "credentials".equals(streamReader.getLocalName())) {
+ gotCredentials = true;
+ if (skipCredentials) {
+ consumeContent(streamReader);
+ } else {
+ credentials = parseCredentials(streamReader, version);
+ }
+ } else if (! gotAttributes && "attributes".equals(streamReader.getLocalName())) {
+ gotAttributes = true;
+ if (skipAttributes) {
+ consumeContent(streamReader);
+ } else {
+ attributes = parseAttributes(streamReader, version);
+ }
+ }
+ streamReader.nextTag();
+ }
+ }
+
+ private List parseCredentials(final XMLStreamReader streamReader, final Version version) throws RealmUnavailableException, XMLStreamException {
+ final int attributeCount = streamReader.getAttributeCount();
+ if (attributeCount > 0) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ if (streamReader.nextTag() == END_ELEMENT) {
+ return Collections.emptyList();
+ }
+ List credentials = new ArrayList<>();
+ do {
+ if (! version.getNamespace().equals(streamReader.getNamespaceURI()) ) {
+ // Mixed versions unsupported.
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ if ("password".equals(streamReader.getLocalName())) {
+ parsePassword(credentials, streamReader, version);
+ } else if ("public-key".equals(streamReader.getLocalName())) {
+ parsePublicKey(credentials, streamReader);
+ } else if ("certificate".equals(streamReader.getLocalName())) {
+ parseCertificate(credentials, streamReader);
+ } else if ("otp".equals(streamReader.getLocalName())) {
+ parseOtp(credentials, streamReader);
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ } while (streamReader.nextTag() != END_ELEMENT);
+ return credentials;
+ }
+
+ private void parseCredential(final XMLStreamReader streamReader, CredentialParseFunction function) throws RealmUnavailableException, XMLStreamException {
+ final int attributeCount = streamReader.getAttributeCount();
+ String name = null;
+ String algorithm = null;
+ String format = null;
+ for (int i = 0; i < attributeCount; i ++) {
+ String namespace = streamReader.getAttributeNamespace(i);
+ if (namespace != null && !namespace.equals("")) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ final String localName = streamReader.getAttributeLocalName(i);
+ if ("name".equals(localName)) {
+ name = streamReader.getAttributeValue(i);
+ } else if ("algorithm".equals(localName)) {
+ algorithm = streamReader.getAttributeValue(i);
+ } else if ("format".equals(localName)) {
+ format = streamReader.getAttributeValue(i);
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ }
+ final String text = streamReader.getElementText().trim();
+ function.parseCredential(algorithm, format, text);
+ }
+
+ private void parseCertificate(final List credentials, final XMLStreamReader streamReader) throws RealmUnavailableException, XMLStreamException {
+ parseCredential(streamReader, (algorithm, format, text) -> {
+ if (algorithm == null) algorithm = X509_FORMAT;
+ if (format == null) format = X509_FORMAT;
+ try {
+ final CertificateFactory certificateFactory = CertificateFactory.getInstance(algorithm);
+ credentials.add(new X509CertificateChainPublicCredential((X509Certificate) certificateFactory.generateCertificate(
+ CodePointIterator.ofString(text).base64Decode().asInputStream())));
+ } catch (CertificateException | ClassCastException e) {
+ throw ElytronMessages.log.fileSystemRealmCertificateReadError(format, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ });
+ }
+
+ private void parsePublicKey(final List credentials, final XMLStreamReader streamReader) throws RealmUnavailableException, XMLStreamException {
+ parseCredential(streamReader, (algorithm, format, text) -> {
+ if (algorithm == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("algorithm", path, streamReader.getLocation().getLineNumber(), name);
+ }
+ if (format == null) {
+ format = X509_FORMAT;
+ } else if (!X509_FORMAT.equals(format)) {
+ throw ElytronMessages.log.fileSystemRealmUnsupportedKeyFormat(format, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ try {
+ KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+ credentials.add(new PublicKeyCredential(keyFactory.generatePublic(new PKCS8EncodedKeySpec(CodePointIterator.ofString(text).base64Decode().drain()))));
+ } catch (NoSuchAlgorithmException e) {
+ throw ElytronMessages.log.fileSystemRealmUnsupportedKeyAlgorithm(format, path, streamReader.getLocation().getLineNumber(), name, e);
+ } catch (InvalidKeySpecException e) {
+ throw ElytronMessages.log.fileSystemRealmUnsupportedKeyFormat(format, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ });
+ }
+
+ private void parsePassword(final List credentials, final XMLStreamReader streamReader, final Version version) throws XMLStreamException, RealmUnavailableException {
+ parseCredential(streamReader, (algorithm, format, text) -> {
+ try {
+ if (ENCRYPTION_FORMAT.equals(format)) {
+ if (! version.isAtLeast(Version.VERSION_1_1)) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ if (algorithm == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("algorithm", path, streamReader.getLocation().getLineNumber(), name);
+ }
+ PasswordFactory passwordFactory = PasswordFactory.getInstance(algorithm, providers);
+ byte[] encryptedPasswordBytes = CodePointIterator.ofChars(text.toCharArray()).base64Decode().drain();
+ byte[] decryptedPasswordBytes;
+ try {
+ decryptedPasswordBytes = CipherUtil.decrypt(encryptedPasswordBytes, secretKey);
+ } catch (GeneralSecurityException e) {
+ throw ElytronMessages.log.fileSystemRealmDecryptionFailed(e);
+ }
+ PasswordSpec passwordSpec = BasicPasswordSpecEncoding.decode(decryptedPasswordBytes);
+
+ if (passwordSpec != null) {
+ credentials.add(new PasswordCredential(passwordFactory.generatePassword(passwordSpec)));
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidPasswordAlgorithm(algorithm, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ } else if (BASE64_FORMAT.equals(format) || HEX.equals(format)) {
+ if (algorithm == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("algorithm", path, streamReader.getLocation().getLineNumber(), name);
+ }
+ PasswordFactory passwordFactory = PasswordFactory.getInstance(algorithm, providers);
+ byte[] passwordBytes;
+ if (BASE64_FORMAT.equals(format)) {
+ passwordBytes = CodePointIterator.ofChars(text.toCharArray()).base64Decode().drain();
+ } else {
+ passwordBytes = CodePointIterator.ofChars(text.toCharArray()).hexDecode().drain();
+ }
+ PasswordSpec passwordSpec = BasicPasswordSpecEncoding.decode(passwordBytes);
+
+ if (passwordSpec != null) {
+ credentials.add(new PasswordCredential(passwordFactory.generatePassword(passwordSpec)));
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidPasswordAlgorithm(algorithm, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ } else if (MCF_FORMAT.equals(format)) {
+ credentials.add(new PasswordCredential(ModularCrypt.decode(text)));
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidPasswordFormat(format, path, streamReader.getLocation().getLineNumber(), name);
+ }
+ } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ });
+ }
+
+ private void parseOtp(final List credentials, final XMLStreamReader streamReader) throws XMLStreamException, RealmUnavailableException {
+ String name = null;
+ String algorithm = null;
+ byte[] hash = null;
+ String seed = null;
+ int sequenceNumber = 0;
+
+ final int attributeCount = streamReader.getAttributeCount();
+ for (int i = 0; i < attributeCount; i ++) {
+ String namespace = streamReader.getAttributeNamespace(i);
+ if (namespace != null && !namespace.equals("")) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ final String localName = streamReader.getAttributeLocalName(i);
+ if ("name".equals(localName)) {
+ name = streamReader.getAttributeValue(i);
+ } else if ("algorithm".equals(localName)) {
+ algorithm = streamReader.getAttributeValue(i);
+ } else if ("hash".equals(localName)) {
+ hash = CodePointIterator.ofString(streamReader.getAttributeValue(i)).base64Decode(Base64Alphabet.STANDARD, false).drain();
+ } else if ("seed".equals(localName)) {
+ seed = new String(CodePointIterator.ofString(streamReader.getAttributeValue(i)).base64Decode(Base64Alphabet.STANDARD, false).drain(), StandardCharsets.US_ASCII);
+ } else if ("sequence".equals(localName)) {
+ sequenceNumber = Integer.parseInt(streamReader.getAttributeValue(i));
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ }
+
+ if (streamReader.nextTag() != END_ELEMENT) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+
+ try {
+ if (algorithm == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("algorithm", path, streamReader.getLocation().getLineNumber(), name);
+ }
+ PasswordFactory passwordFactory = PasswordFactory.getInstance(algorithm, providers);
+ Password password = passwordFactory.generatePassword(new OneTimePasswordSpec(hash, seed, sequenceNumber));
+ credentials.add(new PasswordCredential(password));
+ } catch (InvalidKeySpecException e) {
+ throw ElytronMessages.log.fileSystemRealmInvalidOtpDefinition(path, streamReader.getLocation().getLineNumber(), name, e);
+ } catch (NoSuchAlgorithmException e) {
+ throw ElytronMessages.log.fileSystemRealmInvalidOtpAlgorithm(algorithm, path, streamReader.getLocation().getLineNumber(), name, e);
+ }
+ }
+
+ private Attributes parseAttributes(final XMLStreamReader streamReader, final Version version) throws RealmUnavailableException, XMLStreamException {
+ final int attributeCount = streamReader.getAttributeCount();
+ if (attributeCount > 0) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ int tag = streamReader.nextTag();
+ if (tag == END_ELEMENT) {
+ return Attributes.EMPTY;
+ }
+ Attributes attributes = new MapAttributes();
+ do {
+ if (! version.getNamespace().equals(streamReader.getNamespaceURI()) ) {
+
+ // Mixed versions unsupported.
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ if ("attribute".equals(streamReader.getLocalName())) {
+ parseAttribute(streamReader, attributes);
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), name);
+ }
+ } while (streamReader.nextTag() == START_ELEMENT);
+ return attributes;
+ }
+
+ private void parseAttribute(final XMLStreamReader streamReader, final Attributes attributes) throws XMLStreamException, RealmUnavailableException {
+ String name = null;
+ String value = null;
+ final int attributeCount = streamReader.getAttributeCount();
+ for (int i = 0; i < attributeCount; i++) {
+ String namespace = streamReader.getAttributeNamespace(i);
+ if (namespace != null && !namespace.equals("")) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), this.name);
+ }
+ if ("name".equals(streamReader.getAttributeLocalName(i))) {
+ name = streamReader.getAttributeValue(i);
+ } else if ("value".equals(streamReader.getAttributeLocalName(i))) {
+ value = streamReader.getAttributeValue(i);
+ } else {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), this.name);
+ }
+ }
+ if (name == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("name", path, streamReader.getLocation().getLineNumber(), this.name);
+ }
+ if (value == null) {
+ throw ElytronMessages.log.fileSystemRealmMissingAttribute("value", path, streamReader.getLocation().getLineNumber(), this.name);
+ }
+ if (secretKey != null) {
+ try {
+ attributes.addLast(CipherUtil.decrypt(name, secretKey), CipherUtil.decrypt(value, secretKey));
+ } catch (GeneralSecurityException e){
+ throw ElytronMessages.log.fileSystemRealmDecryptionFailed(e);
+ }
+ } else {
+ attributes.addLast(name, value);
+ }
+ if (streamReader.nextTag() != END_ELEMENT) {
+ throw ElytronMessages.log.fileSystemRealmInvalidContent(path, streamReader.getLocation().getLineNumber(), this.name);
+ }
+ }
+
+ private void consumeContent(final XMLStreamReader reader) throws XMLStreamException {
+ while (reader.hasNext()) {
+ switch (reader.next()) {
+ case START_ELEMENT: {
+ consumeContent(reader);
+ break;
+ }
+ case END_ELEMENT: {
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean isIntegrityValid() {
+ if (this.publicKey != null) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ Document doc;
+ try {
+ doc = dbf.newDocumentBuilder().parse(path.toString());
+ } catch (SAXException | IOException | ParserConfigurationException e) {
+ return false;
+ }
+ return (validatePrincipalName(doc) && validateDigitalSignature(doc));
+ }
+ return true;
+ }
+
+ // Process for updating identity:
+ // 1. Validate current identity digital signature
+ // 2. Update identity with new data
+ // 3. Create new digital signature
+ private boolean validateDigitalSignature(Document doc) {
+ try {
+ NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+ if (nl.getLength() == 0) {
+ throw ElytronMessages.log.cannotFindSignature(path.toString());
+ }
+ XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
+ DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(0));
+ XMLSignature signature = fac.unmarshalXMLSignature(valContext);
+ boolean coreValidity = signature.validate(valContext);
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification against signature for credential [%s] = %b", name, coreValidity);
+ return coreValidity;
+ } catch (IOException | MarshalException | XMLSignatureException e) {
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - Error during verification. Signature for credential [%s] failed", name);
+ return false;
+ }
+ }
+
+ private boolean validatePrincipalName(Document doc) {
+ NodeList nl = doc.getElementsByTagName("principal");
+ if (nl.getLength() == 0) {
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification against principal for credential [%s] = %b", name, false);
+ return false;
+ }
+ String principalName = nl.item(0).getAttributes().getNamedItem("name").getNodeValue();
+ if (secretKey != null) {
+ try {
+ principalName = CipherUtil.decrypt(principalName, secretKey);
+ } catch (GeneralSecurityException e) {
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification against principal for credential [%s] = %b", name, false);
+ return false;
+ }
+ }
+ boolean validity = Objects.equals(principalName, name);
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - verification against principal for credential [%s] = %b", name, validity);
+ return validity;
+ }
+
+ private void writeDigitalSignature(Path path, String name) throws RealmUnavailableException {
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ DocumentBuilder builder = dbf.newDocumentBuilder();
+ Document doc = builder.parse(Files.newInputStream(path));
+ Element elem = doc.getDocumentElement();
+ NodeList signatureNode = doc.getElementsByTagName("Signature");
+ if (signatureNode.getLength() > 0) {
+ Node sig = signatureNode.item(0);
+ elem.removeChild(sig);
+ }
+ DOMSignContext dsc = new DOMSignContext(this.privateKey, elem);
+ XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
+ Reference ref = fac.newReference
+ ("", fac.newDigestMethod(DigestMethod.SHA256, null),
+ Collections.singletonList
+ (fac.newTransform(Transform.ENVELOPED,
+ (TransformParameterSpec) null)), null, null);
+ String signatureMethod = "";
+ // https://issues.redhat.com/browse/ELY-2346
+ // Once JDK 8 support is removed use the javax.xml.crypto.dsig.SignatureMethod to set these signatureMethods
+ switch (this.publicKey.getAlgorithm()) {
+ case "DSA":
+ signatureMethod = "http://www.w3.org/2009/xmldsig11#dsa-sha256";
+ break;
+ case "RSA":
+ signatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
+ break;
+ case "HMAC":
+ signatureMethod = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
+ break;
+ case "EC":
+ signatureMethod = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256";
+ break;
+ }
+ SignedInfo si = fac.newSignedInfo
+ (fac.newCanonicalizationMethod
+ (CanonicalizationMethod.INCLUSIVE,
+ (C14NMethodParameterSpec) null),
+ fac.newSignatureMethod(signatureMethod, null),
+ Collections.singletonList(ref));
+ KeyInfoFactory kif = fac.getKeyInfoFactory();
+ KeyValue kv = kif.newKeyValue(this.publicKey);
+ KeyInfo ki = kif.newKeyInfo(Collections.singletonList(kv));
+ XMLSignature signature = fac.newXMLSignature(si, ki);
+ signature.sign(dsc);
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ DOMSource source = new DOMSource(doc);
+ FileWriter writer = new FileWriter(String.valueOf(path));
+ StreamResult result = new StreamResult(writer);
+ transformer.transform(source, result);
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - signature against file updated [%s]", name);
+ writer.close();
+ } catch (ParserConfigurationException | IOException | NoSuchAlgorithmException | InvalidAlgorithmParameterException |
+ KeyException | XMLSignatureException | MarshalException | TransformerException | SAXException e) {
+ ElytronMessages.log.tracef("FileSystemSecurityRealm - Error during signature generation against identity [%s]", name);
+ throw ElytronMessages.log.unableToGenerateSignature(String.valueOf(this.path));
+ }
+ }
+ }
+
+ protected static final class LoadedIdentity {
+ private final String name;
+ private final List credentials;
+ private final Attributes attributes;
+ private final Encoding hashEncoding;
+
+ LoadedIdentity(final String name, final List credentials, final Attributes attributes, final Encoding hashEncoding) {
+ this.name = name;
+ this.credentials = credentials;
+ this.attributes = attributes;
+ this.hashEncoding = hashEncoding;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Attributes getAttributes() {
+ return attributes;
+ }
+
+ List getCredentials() {
+ return credentials;
+ }
+
+ public Encoding getHashEncoding() {
+ return hashEncoding;
+ }
+
+ }
+
+ static class AutoCloseableXMLStreamReaderHolder implements AutoCloseable {
+ private final XMLStreamReader xmlStreamReader;
+
+ AutoCloseableXMLStreamReaderHolder(final XMLStreamReader xmlStreamReader) {
+ this.xmlStreamReader = xmlStreamReader;
+ }
+
+ public void close() throws XMLStreamException {
+ xmlStreamReader.close();
+ }
+
+ public XMLStreamReader getXmlStreamReader() {
+ return xmlStreamReader;
+ }
+ }
+
+ static class AutoCloseableXMLStreamWriterHolder implements AutoCloseable {
+ private final XMLStreamWriter xmlStreamWriter;
+
+ AutoCloseableXMLStreamWriterHolder(final XMLStreamWriter xmlStreamWriter) {
+ this.xmlStreamWriter = xmlStreamWriter;
+ }
+
+ public void close() throws XMLStreamException {
+ xmlStreamWriter.close();
+ }
+
+ public XMLStreamWriter getXmlStreamWriter() {
+ return xmlStreamWriter;
+ }
+ }
+
+ public static class IntegrityResult {
+ /**
+ * The result of the integrity check and invalid identities.
+ */
+ private final boolean valid;
+ private final ArrayList identityNames;
+
+ IntegrityResult(final boolean valid, final ArrayList identityNames) {
+ this.valid = valid;
+ this.identityNames = identityNames;
+ }
+
+ /**
+ * The validity of the integrity check.
+ *
+ * @return {@code true} if the integrity check was successful.
+ */
+ public boolean isValid() {
+ return valid;
+ }
+
+ /**
+ * Returns a string of the identities that were found to be invalid.
+ *
+ * @return the list of identities that were found to be invalid.
+ */
+ public String getIdentityNames() {
+ return identityNames.toString();
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealmBuilder.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealmBuilder.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/FileSystemSecurityRealmBuilder.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2021 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wildfly.security.auth.realm;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.util.function.Supplier;
+
+import javax.crypto.SecretKey;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.server.NameRewriter;
+import org.wildfly.security.password.spec.Encoding;
+
+
+/**
+ * A builder class that creates {@link FileSystemSecurityRealm} instances.
+ *
+ * @author Ashpan Raskar
+ */
+public class FileSystemSecurityRealmBuilder {
+
+ private Path root;
+ private NameRewriter nameRewriter;
+ private int levels = 2;
+ private boolean encoded = true;
+ private Charset hashCharset;
+ private Encoding hashEncoding;
+ private SecretKey secretKey;
+ private PrivateKey privateKey;
+ private PublicKey publicKey;
+ private Supplier providers;
+
+ FileSystemSecurityRealmBuilder() {
+ }
+
+ /**
+ * Set the root path to be used by the realm.
+ *
+ * @param root the root path of the identity store (must not be {@code null})
+ * @return this builder.enc
+ */
+ public FileSystemSecurityRealmBuilder setRoot(final Path root) {
+ Assert.checkNotNullParam("root", root);
+ this.root = root;
+ return this;
+ }
+
+ /**
+ * Set the name rewriter to be used by the realm.
+ *
+ * @param nameRewriter the name rewriter to apply to looked up names (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setNameRewriter(final NameRewriter nameRewriter) {
+ Assert.checkNotNullParam("nameRewriter", nameRewriter);
+ this.nameRewriter = nameRewriter;
+ return this;
+ }
+
+ /**
+ * Set the number of levels to be used by the realm.
+ *
+ * @param levels the number of levels of directory hashing to apply
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setLevels(final int levels) {
+ Assert.checkMinimumParameter("levels", 0, levels);
+ this.levels = levels;
+ return this;
+ }
+
+ /**
+ * Set whether the identity name should be encoded for the filename in the realm.
+ *
+ * @param encoded whether identity names should be BASE32 encoded before using as filename (only applies if the security realm is unencrypted)
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setEncoded(final boolean encoded) {
+ this.encoded = encoded;
+ return this;
+ }
+
+ /**
+ * Set the character set to be used by the realm.
+ *
+ * @param hashCharset the character set to use when converting password strings to a byte array. Uses UTF-8 by default. (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setHashCharset(final Charset hashCharset) {
+ Assert.checkNotNullParam("hashCharset", hashCharset);
+ this.hashCharset = hashCharset;
+ return this;
+ }
+
+ /**
+ * Set the string format for hashed passwords to be used by the realm.
+ *
+ * @param hashEncoding the string format for the hashed passwords. Uses Base64 by default. (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setHashEncoding(final Encoding hashEncoding) {
+ Assert.checkNotNullParam("hashEncoding", hashEncoding);
+ this.hashEncoding = hashEncoding;
+ return this;
+ }
+
+ /**
+ * Set the SecretKey to be used by the realm.
+ *
+ * @param secretKey the symmetric SecretKey used to encrypt and decrypt the Security Realm (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setSecretKey(final SecretKey secretKey) {
+ Assert.checkNotNullParam("secretKey", secretKey);
+ this.secretKey = secretKey;
+ return this;
+ }
+
+ /**
+ * Set the providers to be used by the realm.
+ *
+ * @param providers the provider to be used (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setProviders(final Supplier providers) {
+ Assert.checkNotNullParam("providers", providers);
+ this.providers = providers;
+ return this;
+ }
+
+ /**
+ * Set the PrivateKey to be used by the realm.
+ *
+ * @param privateKey the asymmetric PrivateKey used to sign the identity files used for file integrity (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setPrivateKey(final PrivateKey privateKey) {
+ Assert.checkNotNullParam("privateKey", privateKey);
+ this.privateKey = privateKey;
+ return this;
+ }
+
+ /**
+ * Set the PublicKey to be used by the realm.
+ *
+ * @param publicKey the asymmetric PublicKey used to verify the identity files used for file integrity (must not be {@code null})
+ * @return this builder.
+ */
+ public FileSystemSecurityRealmBuilder setPublicKey(final PublicKey publicKey) {
+ Assert.checkNotNullParam("publicKey", publicKey);
+ this.publicKey = publicKey;
+ return this;
+ }
+
+ /**
+ * Builds a new {@link FileSystemSecurityRealm} instance based on configuration defined for this {@link FileSystemSecurityRealmBuilder} instance.
+ *
+ * @return the built realm
+ */
+ public FileSystemSecurityRealm build() {
+ encoded = secretKey == null && encoded;
+ if (nameRewriter == null) {
+ nameRewriter = NameRewriter.IDENTITY_REWRITER;
+ }
+ if (hashEncoding == null) {
+ hashEncoding = Encoding.BASE64;
+ }
+ if (hashCharset == null) {
+ hashCharset = StandardCharsets.UTF_8;
+ }
+ if (privateKey == null ^ publicKey == null) {
+ throw ElytronMessages.log.invalidKeyPairArgument(root.toString());
+ }
+
+ return new FileSystemSecurityRealm(root, nameRewriter, levels, encoded, hashEncoding, hashCharset, providers, secretKey, privateKey, publicKey);
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IdentitySharedExclusiveLock.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IdentitySharedExclusiveLock.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IdentitySharedExclusiveLock.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,148 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2016 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+/**
+ * A simple shared/exclusive lock for a realm identity.
+ *
+ * @author Farah Juma
+ */
+public class IdentitySharedExclusiveLock {
+
+ private int sharedHoldCount;
+ private boolean isExclusiveLocked;
+ private int exclusiveRequests;
+
+ /**
+ * Acquire the exclusive lock. An invocation of this method will block until the lock can be acquired.
+ *
+ * @return a lock object representing the newly acquired lock
+ */
+ public synchronized IdentityLock lockExclusive() {
+ boolean interrupted = false;
+ try {
+ exclusiveRequests++;
+ while ((sharedHoldCount > 0) || isExclusiveLocked) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ isExclusiveLocked = true;
+ exclusiveRequests--;
+ return new IdentityLock(true);
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ }
+
+ /**
+ * Acquire a shared lock. An invocation of this method will block until the lock can be acquired.
+ *
+ * @return a lock object representing the newly acquired lock
+ */
+ public synchronized IdentityLock lockShared() {
+ boolean interrupted = false;
+ try {
+ while (isExclusiveLocked || (exclusiveRequests > 0)) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ sharedHoldCount++;
+ return new IdentityLock(false);
+ } finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ private synchronized void release(IdentityLock identityLock) {
+ if (identityLock.isExclusive()) {
+ isExclusiveLocked = false;
+ notifyAll();
+ } else {
+ if (--sharedHoldCount == 0) {
+ notifyAll();
+ }
+ }
+
+ }
+
+ /**
+ * Class that represents a lock on a realm identity. A lock object is created each time a lock is
+ * acquired on a realm identity via {@link IdentitySharedExclusiveLock#lockExclusive()} or
+ * {@link IdentitySharedExclusiveLock#lockShared()}.
+ */
+ public class IdentityLock implements AutoCloseable {
+
+ private final boolean exclusive;
+ private volatile boolean valid = true;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param exclusive {@code true} if this lock is exclusive, {@code false} if this lock is shared
+ */
+ public IdentityLock(final boolean exclusive) {
+ this.exclusive = exclusive;
+ }
+
+ /**
+ * Release this lock. Invoking this method has no effect if this lock is invalid.
+ */
+ public synchronized void release() {
+ if (valid) {
+ IdentitySharedExclusiveLock.this.release(this);
+ valid = false;
+ }
+ }
+
+ @Override
+ public void close() {
+ release();
+ }
+
+ /**
+ * Determine whether this lock is exclusive or shared.
+ *
+ * @return {@code true} if this lock is exclusive, {@code false} if this lock is shared
+ */
+ public boolean isExclusive() {
+ return exclusive;
+ }
+
+ /**
+ * Determine whether this lock is valid. A lock starts out valid and becomes invalid when it
+ * is released via {@link #release()} or {@link #close()}.
+ *
+ * @return {@code true} if this lock is valid, {@code false} otherwise
+ */
+ public boolean isValid() {
+ return valid;
+ }
+ }
+}
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IntegrityException.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IntegrityException.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/IntegrityException.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2022 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import java.io.IOException;
+
+/**
+ * Exception to indicate a general failure related to the Integrity Verification of the Filesystem Realm.
+ *
+ * @author Ashpan Raskar
+ */
+public class IntegrityException extends IOException {
+
+
+ private static final long serialVersionUID = 8889252552074803941L;
+
+ /**
+ * Constructs a new {@code IntegrityException} instance. The message is left blank ({@code null}), and no
+ * cause is specified.
+ */
+ public IntegrityException() {
+ }
+
+ /**
+ * Constructs a new {@code IntegrityException} instance with an initial message. No cause is specified.
+ *
+ * @param msg the message
+ */
+ public IntegrityException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new {@code IntegrityException} instance with an initial cause. If a non-{@code null} cause
+ * is specified, its message is used to initialize the message of this {@code IntegrityException}; otherwise
+ * the message is left blank ({@code null}).
+ *
+ * @param cause the cause
+ */
+ public IntegrityException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new {@code IntegrityException} instance with an initial message and cause.
+ *
+ * @param msg the message
+ * @param cause the cause
+ */
+ public IntegrityException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
+
Index: 3rdParty_sources/elytron/org/wildfly/security/auth/realm/JaasSecurityRealm.java
===================================================================
diff -u
--- 3rdParty_sources/elytron/org/wildfly/security/auth/realm/JaasSecurityRealm.java (revision 0)
+++ 3rdParty_sources/elytron/org/wildfly/security/auth/realm/JaasSecurityRealm.java (revision 5e9e3c6915701ed7a340d47ff6d32c12ccb9e800)
@@ -0,0 +1,418 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2014 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.wildfly.security.auth.realm;
+
+import static org.wildfly.security.auth.realm.ElytronMessages.log;
+
+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.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.Paths;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.Security;
+import java.security.URIParameter;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.wildfly.common.Assert;
+import org.wildfly.security.auth.callback.CredentialCallback;
+import org.wildfly.security.auth.principal.NamePrincipal;
+import org.wildfly.security.authz.Attributes;
+import org.wildfly.security.authz.AuthorizationIdentity;
+import org.wildfly.security.auth.server.RealmIdentity;
+import org.wildfly.security.auth.server.RealmUnavailableException;
+import org.wildfly.security.auth.server.SecurityRealm;
+import org.wildfly.security.auth.SupportLevel;
+import org.wildfly.security.authz.MapAttributes;
+import org.wildfly.security.credential.Credential;
+import org.wildfly.security.evidence.Evidence;
+import org.wildfly.security.evidence.PasswordGuessEvidence;
+
+/**
+ * A JAAS based {@link SecurityRealm} implementation.
+ *
+ * @author Stefan Guilhen
+ */
+public class JaasSecurityRealm implements SecurityRealm {
+
+ private static final String DEFAULT_CONFIGURATION_POLICY_TYPE = "JavaLoginConfig";
+ private final URI jaasConfigFilePath;
+ private final String entry;
+ private final CallbackHandler handler;
+ private final ClassLoader classLoader;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param entry JAAS configuration file entry (must not be {@code null})
+ */
+ public JaasSecurityRealm(final String entry) {
+ this(entry, (String) null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param entry JAAS configuration file entry (must not be {@code null})
+ * @param classLoader classLoader to use with LoginContext, this class loader must contain LoginModule CallbackHandler classes
+ */
+ public JaasSecurityRealm(final String entry, final ClassLoader classLoader) {
+ this(entry, null, classLoader);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param entry JAAS configuration file entry (must not be {@code null})
+ * @param jaasConfigFilePath path to JAAS configuration file
+ */
+ public JaasSecurityRealm(final String entry, final String jaasConfigFilePath) {
+ this(entry, jaasConfigFilePath, null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param entry JAAS configuration file entry (must not be {@code null})
+ * @param jaasConfigFilePath path to JAAS configuration file
+ * @param classLoader classLoader to use with LoginContext, this class loader must contain LoginModule CallbackHandler classes
+ */
+ public JaasSecurityRealm(final String entry, final String jaasConfigFilePath, final ClassLoader classLoader) {
+ this(entry, jaasConfigFilePath, classLoader, null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param entry JAAS configuration file entry (must not be {@code null})
+ * @param jaasConfigFilePath path to JAAS configuration file
+ * @param callbackHandler callbackHandler to pass to LoginContext
+ * @param classLoader classLoader to use with LoginContext, this class loader must contain LoginModule CallbackHandler classes
+ */
+ public JaasSecurityRealm(final String entry, final String jaasConfigFilePath, final ClassLoader classLoader, final CallbackHandler callbackHandler) {
+ Assert.checkNotNullParam("entry", entry);
+ if (jaasConfigFilePath != null) {
+ this.jaasConfigFilePath = Paths.get(jaasConfigFilePath).toUri();
+ } else {
+ this.jaasConfigFilePath = null;
+ }
+ this.entry = entry;
+ this.handler = callbackHandler;
+ if (classLoader != null) {
+ this.classLoader = classLoader;
+ } else {
+ this.classLoader = Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ @Override
+ public RealmIdentity getRealmIdentity(final Principal principal) {
+ if (principal instanceof NamePrincipal) {
+ return new JaasRealmIdentity(principal);
+ } else {
+ NamePrincipal namePrincipal = NamePrincipal.from(principal);
+ return namePrincipal != null ? new JaasRealmIdentity(namePrincipal) : RealmIdentity.NON_EXISTENT;
+ }
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ Assert.checkNotNullParam("credentialType", credentialType);
+ return SupportLevel.UNSUPPORTED;
+ }
+
+ @Override
+ public SupportLevel getEvidenceVerifySupport(final Class extends Evidence> evidenceType, final String algorithmName) throws RealmUnavailableException {
+ Assert.checkNotNullParam("evidenceType", evidenceType);
+ return SupportLevel.POSSIBLY_SUPPORTED;
+ }
+
+ private class JaasRealmIdentity implements RealmIdentity {
+
+ private final Principal principal;
+ private LoginContext loginContext;
+ private Subject subject;
+
+ private JaasRealmIdentity(final Principal principal) {
+ this.principal = principal;
+ }
+
+ public Principal getRealmIdentityPrincipal() {
+ return principal;
+ }
+
+ public Subject getSubject() {
+ return subject;
+ }
+
+ @Override
+ public SupportLevel getCredentialAcquireSupport(final Class extends Credential> credentialType, final String algorithmName, final AlgorithmParameterSpec parameterSpec) throws RealmUnavailableException {
+ return JaasSecurityRealm.this.getCredentialAcquireSupport(credentialType, algorithmName, parameterSpec);
+ }
+
+ @Override
+ public C getCredential(final Class credentialType) throws RealmUnavailableException {
+ return getCredential(credentialType, null);
+ }
+
+ @Override
+ public