All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.security.sasl.util.SaslMechanismInformation Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * 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.sasl.util;

import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
import static java.util.Collections.unmodifiableSet;

import java.security.Principal;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Predicate;

import org.wildfly.security.credential.BearerTokenCredential;
import org.wildfly.security.credential.Credential;
import org.wildfly.security.credential.GSSKerberosCredential;
import org.wildfly.security.credential.PasswordCredential;
import org.wildfly.security.credential.X509CertificateChainPublicCredential;
import org.wildfly.security.evidence.AlgorithmEvidence;
import org.wildfly.security.evidence.BearerTokenEvidence;
import org.wildfly.security.evidence.Evidence;
import org.wildfly.security.evidence.PasswordGuessEvidence;
import org.wildfly.security.password.OneWayPassword;
import org.wildfly.security.password.Password;
import org.wildfly.security.password.TwoWayPassword;
import org.wildfly.security.password.interfaces.ClearPassword;
import org.wildfly.security.password.interfaces.DigestPassword;
import org.wildfly.security.password.interfaces.OneTimePassword;
import org.wildfly.security.password.interfaces.ScramDigestPassword;
import org.wildfly.security.credential.X509CertificateChainPrivateCredential;

/**
 * A collection of predicates and other information which can be used to filter SASL mechanisms.
 *
 * @see FilterMechanismSaslClientFactory
 * @see FilterMechanismSaslServerFactory
 * @author David M. Lloyd
 */
public final class SaslMechanismInformation {

    public static final class Names {
        public static final String CRAM_MD5 = "CRAM-MD5";
        public static final String DIGEST_MD5 = "DIGEST-MD5";
        public static final String DIGEST_SHA = "DIGEST-SHA";
        public static final String DIGEST_SHA_256 = "DIGEST-SHA-256";
        public static final String DIGEST_SHA_384 = "DIGEST-SHA-384";
        public static final String DIGEST_SHA_512 = "DIGEST-SHA-512";
        public static final String DIGEST_SHA_512_256 = "DIGEST-SHA-512-256";
        public static final String SCRAM_SHA_1 = "SCRAM-SHA-1";
        public static final String SCRAM_SHA_1_PLUS = "SCRAM-SHA-1-PLUS";
        public static final String SCRAM_SHA_256 = "SCRAM-SHA-256";
        public static final String SCRAM_SHA_256_PLUS = "SCRAM-SHA-256-PLUS";
        public static final String SCRAM_SHA_384 = "SCRAM-SHA-384";
        public static final String SCRAM_SHA_384_PLUS = "SCRAM-SHA-384-PLUS";
        public static final String SCRAM_SHA_512 = "SCRAM-SHA-512";
        public static final String SCRAM_SHA_512_PLUS = "SCRAM-SHA-512-PLUS";
        public static final String IEC_ISO_9798_M_DSA_SHA1 = "9798-M-DSA-SHA1";
        public static final String IEC_ISO_9798_M_ECDSA_SHA1 = "9798-M-ECDSA-SHA1";
        public static final String IEC_ISO_9798_M_RSA_SHA1_ENC = "9798-M-RSA-SHA1-ENC";
        public static final String IEC_ISO_9798_U_DSA_SHA1 = "9798-U-DSA-SHA1";
        public static final String IEC_ISO_9798_U_ECDSA_SHA1 = "9798-U-ECDSA-SHA1";
        public static final String IEC_ISO_9798_U_RSA_SHA1_ENC = "9798-U-RSA-SHA1-ENC";
        public static final String ANONYMOUS = "ANONYMOUS";
        public static final String EAP_AES128 = "EAP-AES128";
        public static final String EAP_AES128_PLUS = "EAP-AES128-PLUS";
        public static final String EXTERNAL = "EXTERNAL";
        public static final String JBOSS_LOCAL_USER = "JBOSS-LOCAL-USER";
        public static final String OAUTH_10_A = "OAUTH10A";
        public static final String OAUTHBEARER = "OAUTHBEARER";
        public static final String OPENID20 = "OPENID20";
        public static final String OTP = "OTP";
        public static final String SAML20 = "SAML20";
        public static final String SECURID = "SECURID";
        public static final String PLAIN = "PLAIN";
        public static final String GS2_KRB5 = "GS2-KRB5";
        public static final String GS2_KRB5_PLUS = "GS2-KRB5-PLUS";
        public static final String GSSAPI = "GSSAPI";

        private Names() {}
    }

    private static final Set MD5_MECHS = nSet(
        Names.CRAM_MD5,
        Names.DIGEST_MD5
    );

    private static final Set SHA_MECHS = nSet(
        Names.DIGEST_SHA,
        Names.SCRAM_SHA_1,
        Names.SCRAM_SHA_1_PLUS
    );

    private static final Set SHA_256_MECHS = nSet(
        Names.DIGEST_SHA_256,
        Names.SCRAM_SHA_256,
        Names.SCRAM_SHA_256_PLUS
    );

    private static final Set SHA_384_MECHS = nSet(
        Names.DIGEST_SHA_384,
        Names.SCRAM_SHA_384,
        Names.SCRAM_SHA_384_PLUS
    );

    private static final Set SHA_512_MECHS = nSet(
        Names.DIGEST_SHA_512,
        Names.SCRAM_SHA_512,
        Names.SCRAM_SHA_512_PLUS
    );

    private static final Set SHA_512_256_MECHS = nSet(
            Names.DIGEST_SHA_512_256
    );

    private static final Set MUTUAL_MECHS = nSet(
        Names.IEC_ISO_9798_M_DSA_SHA1,
        Names.IEC_ISO_9798_M_ECDSA_SHA1,
        Names.IEC_ISO_9798_M_RSA_SHA1_ENC
    );

    private static final Set RECOMMENDED_MECHS = nSet(
        Names.IEC_ISO_9798_M_DSA_SHA1,
        Names.IEC_ISO_9798_M_ECDSA_SHA1,
        Names.IEC_ISO_9798_M_RSA_SHA1_ENC,
        Names.IEC_ISO_9798_U_DSA_SHA1,
        Names.IEC_ISO_9798_U_ECDSA_SHA1,
        Names.IEC_ISO_9798_U_RSA_SHA1_ENC,
        Names.ANONYMOUS,
        Names.EAP_AES128,
        Names.EAP_AES128_PLUS,
        Names.EXTERNAL,
        Names.OAUTH_10_A,
        Names.OAUTHBEARER,
        Names.OPENID20,
        Names.OTP,
        Names.SAML20,
        Names.SECURID
    );

    /**
     * A predicate which is true when the mechanism uses MD5.
     */
    public static final Predicate HASH_MD5 = MD5_MECHS::contains;

    /**
     * A predicate which is true when the mechanism uses SHA.
     */
    public static final Predicate HASH_SHA = SHA_MECHS::contains;

    /**
     * A predicate which is true when the mechanism uses SHA-256.
     */
    public static final Predicate HASH_SHA_256 = SHA_256_MECHS::contains;

    /**
     * A predicate which is true when the mechanism uses SHA-384.
     */
    public static final Predicate HASH_SHA_384 = SHA_384_MECHS::contains;

    /**
     * A predicate which is true when the mechanism uses SHA-512.
     */
    public static final Predicate HASH_SHA_512 = SHA_512_MECHS::contains;

    /**
     * A predicate which is true when the mechanism uses SHA-512/256.
     */
    public static final Predicate HASH_SHA_512_256 = SHA_512_256_MECHS::contains;

    /**
     * A predicate which is true when a GS2-family mechanism is being used.
     */
    public static final Predicate GS2 = name -> name.startsWith("GS2-");

    /**
     * A predicate which is true when a SCRAM-family mechanism is being used.
     */
    public static final Predicate SCRAM = name -> name.startsWith("SCRAM-");

    /**
     * A predicate which is true when a DIGEST-family mechanism is being used.
     */
    public static final Predicate DIGEST = name -> name.startsWith("DIGEST-");

    /**
     * A predicate which is true when a IEC/ISO-9798-family mechanism is being used.
     */
    public static final Predicate IEC_ISO_9798 = name -> name.startsWith("9798-");

    /**
     * A predicate which is true when an EAP-family mechanism is being used.
     */
    public static final Predicate EAP = name -> name.startsWith("EAP-");

    /**
     * A predicate which is true when the mechanism supports mutual authentication.
     */
    public static final Predicate MUTUAL = ((Predicate) MUTUAL_MECHS::contains).or(SCRAM).or(GS2);

    /**
     * A predicate which is true when a mechanism which uses channel binding is being used.
     */
    public static final Predicate BINDING = name -> name.endsWith("-PLUS");

    /**
     * A predicate which is true when the name being tested is a recommended mechanism as of the time of this release.
     */
    public static final Predicate RECOMMENDED = ((Predicate) RECOMMENDED_MECHS::contains).or(GS2).or(SCRAM).and(HASH_MD5.negate());

    // credential type sets

    static final Set> JUST_ONE_WAY = singleton(OneTimePassword.class);
    static final Set> JUST_TWO_WAY = singleton(TwoWayPassword.class);
    static final Set> ONE_WAY_AND_TWO_WAY = nSet(OneWayPassword.class, TwoWayPassword.class);
    static final Set> DIGEST_AND_TWO_WAY = nSet(DigestPassword.class, TwoWayPassword.class);
    static final Set> SCRAM_AND_TWO_WAY = nSet(ScramDigestPassword.class, TwoWayPassword.class);

    static final Set> JUST_X509 = singleton(X509CertificateChainPrivateCredential.class);
    static final Set> X_509_PUBLIC_OR_PRIVATE = nSet(X509CertificateChainPublicCredential.class, X509CertificateChainPrivateCredential.class);
    static final Set> JUST_PASSWORD = singleton(PasswordCredential.class);
    static final Set> JUST_GSS = singleton(GSSKerberosCredential.class);
    static final Set> JUST_BEARER_TOKEN = singleton(BearerTokenCredential.class);

    static final Set> JUST_PASSWORD_EVIDENCE = singleton(PasswordGuessEvidence.class);

    static final Set> JUST_BEARER_TOKEN_EVIDENCE = singleton(BearerTokenEvidence.class);

    // algorithm name sets

    static final Set DIGEST_MD5_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_MD5, ClearPassword.ALGORITHM_CLEAR);
    static final Set DIGEST_SHA_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_SHA, ClearPassword.ALGORITHM_CLEAR);
    static final Set DIGEST_SHA_256_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_SHA_256, ClearPassword.ALGORITHM_CLEAR);
    static final Set DIGEST_SHA_384_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_SHA_384, ClearPassword.ALGORITHM_CLEAR);
    static final Set DIGEST_SHA_512_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_SHA_512, ClearPassword.ALGORITHM_CLEAR);
    static final Set DIGEST_SHA_512_256_AND_PLAIN = nSet(DigestPassword.ALGORITHM_DIGEST_SHA_512_256, ClearPassword.ALGORITHM_CLEAR);
    static final Set SCRAM_SHA_1_AND_PLAIN = nSet(ScramDigestPassword.ALGORITHM_SCRAM_SHA_1, ClearPassword.ALGORITHM_CLEAR);
    static final Set SCRAM_SHA_256_AND_PLAIN = nSet(ScramDigestPassword.ALGORITHM_SCRAM_SHA_256, ClearPassword.ALGORITHM_CLEAR);
    static final Set SCRAM_SHA_384_AND_PLAIN = nSet(ScramDigestPassword.ALGORITHM_SCRAM_SHA_384, ClearPassword.ALGORITHM_CLEAR);
    static final Set SCRAM_SHA_512_AND_PLAIN = nSet(ScramDigestPassword.ALGORITHM_SCRAM_SHA_512, ClearPassword.ALGORITHM_CLEAR);
    static final Set OTP_ALGORITHMS = nSet(OneTimePassword.ALGORITHM_OTP_MD5, OneTimePassword.ALGORITHM_OTP_SHA1,
            OneTimePassword.ALGORITHM_OTP_SHA_256, OneTimePassword.ALGORITHM_OTP_SHA_384,
            OneTimePassword.ALGORITHM_OTP_SHA_512);
    static final Set JUST_PLAIN = singleton(ClearPassword.ALGORITHM_CLEAR);
    static final Set JUST_DSA = singleton("DSA");
    static final Set JUST_EC = singleton("EC");
    static final Set JUST_RSA = singleton("RSA");
    static final Set ALL_ALGORITHMS = singleton("*");

    /**
     * Get the supported credential types for the given SASL client mechanism.  If an empty set is returned, then no
     * credentials are used by the mechanism or the mechanism is not known.
     *
     * @param mechName the mechanism name
     * @return the set of allowed client credentials
     */
    public static Set> getSupportedClientCredentialTypes(String mechName) {
        switch (mechName) {
            case Names.EXTERNAL:
            case Names.ANONYMOUS: {
                return emptySet();
            }
            case Names.PLAIN:
            case Names.OTP:
            case Names.CRAM_MD5:
            case Names.DIGEST_MD5:
            case Names.DIGEST_SHA:
            case Names.DIGEST_SHA_256:
            case Names.DIGEST_SHA_384:
            case Names.DIGEST_SHA_512:
            case Names.DIGEST_SHA_512_256:
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS:
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS:
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS:
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return JUST_PASSWORD;
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                return X_509_PUBLIC_OR_PRIVATE;
            }
            case Names.OAUTHBEARER: {
                return JUST_BEARER_TOKEN;
            }
            case Names.GSSAPI: {
                return JUST_GSS;
            }
            default: {
                if (GS2.test(mechName)) {
                    return JUST_GSS;
                }
                // unknown
                return emptySet();
            }
        }
    }

    /**
     * Get the supported password types for the given SASL client mechanism.  If an empty set is returned, then no
     * passwords are used by the mechanism or nothing is known about the mechanism.
     *
     * @param mechName the mechanism name
     * @return the set of allowed client password types
     */
    public static Set> getSupportedClientPasswordTypes(String mechName) {
        switch (mechName) {
            case Names.EXTERNAL:
            case Names.ANONYMOUS: {
                return emptySet();
            }
            case Names.PLAIN:
            case Names.OTP:
            case Names.CRAM_MD5: {
                return JUST_TWO_WAY;
            }
            case Names.DIGEST_MD5:
            case Names.DIGEST_SHA:
            case Names.DIGEST_SHA_256:
            case Names.DIGEST_SHA_384:
            case Names.DIGEST_SHA_512:
            case Names.DIGEST_SHA_512_256: {
                return DIGEST_AND_TWO_WAY;
            }
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS:
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS:
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS:
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return SCRAM_AND_TWO_WAY;
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                return emptySet();
            }
            default: {
                // unknown
                return emptySet();
            }
        }
    }

    /**
     * Get the supported credential types for the given SASL server mechanism.  If an empty set is returned, then no
     * credentials are used by the mechanism or the mechanism is unknown.
     *
     * @param mechName the mechanism name
     * @return the set of allowed server credential types
     */
    public static Set> getSupportedServerCredentialTypes(String mechName) {
        switch (mechName) {
            case Names.EXTERNAL:
            case Names.ANONYMOUS: {
                return emptySet();
            }
            case Names.PLAIN:
            case Names.OTP:
            case Names.CRAM_MD5:
            case Names.DIGEST_MD5:
            case Names.DIGEST_SHA:
            case Names.DIGEST_SHA_256:
            case Names.DIGEST_SHA_384:
            case Names.DIGEST_SHA_512:
            case Names.DIGEST_SHA_512_256:
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS:
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS:
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS:
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return JUST_PASSWORD;
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                // TODO: look into verification process
                return JUST_X509;
            }
            case Names.GSSAPI: {
                return JUST_GSS;
            }
            default: {
                if (GS2.test(mechName)) {
                    return JUST_GSS;
                }
                // unknown
                return emptySet();
            }
        }
    }

    /**
     * Get the supported password types for the given SASL server mechanism.  If an empty set is returned, then no
     * passwords are used by the mechanism or nothing is known about the mechanism
     *
     * @param mechName the mechanism name
     * @return the set of allowed server password types
     */
    public static Set> getSupportedServerPasswordTypes(String mechName) {
        switch (mechName) {
            case Names.EXTERNAL:
            case Names.ANONYMOUS: {
                return emptySet();
            }
            case Names.PLAIN: {
                return ONE_WAY_AND_TWO_WAY;
            }
            case Names.OTP: {
                return JUST_ONE_WAY;
            }
            case Names.CRAM_MD5: {
                return JUST_TWO_WAY;
            }
            case Names.DIGEST_MD5:
            case Names.DIGEST_SHA:
            case Names.DIGEST_SHA_256:
            case Names.DIGEST_SHA_384:
            case Names.DIGEST_SHA_512: {
                return DIGEST_AND_TWO_WAY;
            }
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS:
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS:
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS:
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return SCRAM_AND_TWO_WAY;
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                return emptySet();
            }
            default: {
                // unknown
                return emptySet();
            }
        }
    }

    /**
     * Get the supported algorithm names for a SASL client mechanism and credential type.  If the mechanism or
     * credential type is not recognized, or if the given credential type does not use algorithms for the
     * given mechanism name, an empty set is returned.  If all algorithms are supported, a set containing the special
     * string {@code "*"} is returned.
     *
     * @param mechName the SASL mechanism name
     * @param credentialType the proposed credential type
     *
     * @return the set of algorithms, or an empty set if all algorithms have unknown support
     */
    public static Set getSupportedClientCredentialAlgorithms(String mechName, Class credentialType) {
        switch (mechName) {
            case Names.CRAM_MD5:
            case Names.PLAIN: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? JUST_PLAIN : emptySet();
            }
            case Names.DIGEST_MD5: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_MD5_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_256: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_256_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_384: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_384_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_512: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_512_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_512_256: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_512_256_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_1_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_256_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_384_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_512_AND_PLAIN : emptySet();
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1: {
                return credentialType.isAssignableFrom(X509CertificateChainPrivateCredential.class) ? JUST_DSA : emptySet();
            }
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1: {
                // todo: double-check
                return credentialType.isAssignableFrom(X509CertificateChainPrivateCredential.class) ? JUST_EC : emptySet();
            }
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                return credentialType.isAssignableFrom(X509CertificateChainPrivateCredential.class) ? JUST_RSA : emptySet();
            }
            default:
                return emptySet();
        }
    }

    /**
     * Get the supported algorithm names for a SASL server mechanism and credential type.  If the mechanism or
     * credential type is not recognized, or if the given credential type does not use algorithms for the
     * given mechanism name, an empty set is returned.  If all algorithms are supported, a set containing the special
     * string {@code "*"} is returned.
     *
     * @param mechName the SASL mechanism name
     * @param credentialType the proposed credential type
     *
     * @return the set of algorithms, or an empty set if all algorithms have equal or unknown support
     */
    public static Set getSupportedServerCredentialAlgorithms(String mechName, Class credentialType) {
        switch (mechName) {
            case Names.PLAIN: {
                return ALL_ALGORITHMS;
            }
            case Names.DIGEST_MD5: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_MD5_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_256: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_256_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_384: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_384_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_512: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_512_AND_PLAIN : emptySet();
            }
            case Names.DIGEST_SHA_512_256: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? DIGEST_SHA_512_256_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_1_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_256_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_384_AND_PLAIN : emptySet();
            }
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? SCRAM_SHA_512_AND_PLAIN : emptySet();
            }
            case Names.OTP: {
                return credentialType.isAssignableFrom(PasswordCredential.class) ? OTP_ALGORITHMS : emptySet();
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                // TODO: look into verification process
                return emptySet();
            }
            default:
                return emptySet();
        }
    }

    /**
     * Get the supported evidence types for the given SASL server mechanism.  If an empty set is returned, then no
     * evidence is used by the mechanism.
     *
     * @param mechName the mechanism name
     * @return the set of allowed server credential types
     */
    public static Set> getSupportedServerEvidenceTypes(final String mechName) {
        switch (mechName) {
            case Names.OTP:
            case Names.CRAM_MD5:
            case Names.PLAIN:
            case Names.DIGEST_MD5:
            case Names.DIGEST_SHA:
            case Names.DIGEST_SHA_256:
            case Names.DIGEST_SHA_384:
            case Names.DIGEST_SHA_512:
            case Names.DIGEST_SHA_512_256:
            case Names.SCRAM_SHA_1:
            case Names.SCRAM_SHA_1_PLUS:
            case Names.SCRAM_SHA_256:
            case Names.SCRAM_SHA_256_PLUS:
            case Names.SCRAM_SHA_384:
            case Names.SCRAM_SHA_384_PLUS:
            case Names.SCRAM_SHA_512:
            case Names.SCRAM_SHA_512_PLUS: {
                return JUST_PASSWORD_EVIDENCE;
            }
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                // TODO: look into verification process
                return emptySet();
            }
            case Names.OAUTHBEARER: {
                return JUST_BEARER_TOKEN_EVIDENCE;
            }
            default:
                return emptySet();
        }
    }

    /**
     * Get the supported algorithm names for a SASL server mechanism and evidence type.  If the mechanism or
     * evidence type is not recognized, or if the given evidence type does not have an algorithm restriction for the
     * given mechanism name, an empty set is returned.
     *
     * @param mechName the SASL mechanism name
     * @param evidenceType the proposed evidence type
     *
     * @return the set of algorithms, or an empty set if all algorithms have equal or unknown support
     */
    public static Set getSupportedServerEvidenceAlgorithms(final String mechName, final Class evidenceType) {
        switch (mechName) {
            case Names.IEC_ISO_9798_M_DSA_SHA1:
            case Names.IEC_ISO_9798_U_DSA_SHA1:
            case Names.IEC_ISO_9798_M_ECDSA_SHA1:
            case Names.IEC_ISO_9798_U_ECDSA_SHA1:
            case Names.IEC_ISO_9798_M_RSA_SHA1_ENC:
            case Names.IEC_ISO_9798_U_RSA_SHA1_ENC: {
                // TODO: look into verification process
                return emptySet();
            }
            default:
                return emptySet();
        }
    }

    /**
     * Determine whether a mechanism needs server-side credentials in order to authenticate.  This may include credential
     * verification or acquisition, or both.
     *
     * @param mechName the mechanism name
     * @return {@code true} if the mechanism uses credentials, {@code false} otherwise
     */
    public static boolean needsServerCredentials(final String mechName) {
        switch (mechName) {
            case Names.ANONYMOUS:
            case Names.EXTERNAL:
            case Names.JBOSS_LOCAL_USER:
            case Names.GSSAPI:
            case Names.GS2_KRB5:
            case Names.GS2_KRB5_PLUS: {
                return false;
            }
            default: {
                return true;
            }
        }
    }

    /**
     * Determine whether the given mechanism name is known to not use any sort of {@link Principal} for authentication.
     *
     * @param mechName the mechanism name (must not be {@code null})
     * @return {@code true} if the mechanism does not use a principal, {@code false} if it does or it is not known
     */
    public static boolean doesNotUsePrincipal(final String mechName) {
        switch (mechName) {
            case Names.ANONYMOUS:
            case Names.EXTERNAL:
            case Names.GSSAPI:
            case Names.OAUTHBEARER: {
                return true;
            }
            default: {
                return false;
            }
        }
    }

    /**
     * Determine whether a mechanism does not need the client to present credentials.
     *
     * @param mechName the mechanism name
     * @return {@code true} if the mechanism does not require client credentials, {@code false} if it it does or it is not known
     */
    public static boolean doesNotRequireClientCredentials(final String mechName) {
        switch (mechName) {
            case Names.JBOSS_LOCAL_USER:
            case Names.ANONYMOUS:
            case Names.GSSAPI:
            case Names.EXTERNAL: {
                return true;
            }
            default: {
                return false;
            }
        }
    }

    @SafeVarargs
    private static  Set nSet(T... values) {
        return unmodifiableSet(new LinkedHashSet<>(asList(values)));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy