Skip to content

Commit

Permalink
Merge pull request #1860 from petrberan/ELY-489
Browse files Browse the repository at this point in the history
[ELY-489] Add JavaDoc for the 'org.wildfly.security.mechanism' package and sub packages
  • Loading branch information
fjuma authored May 7, 2024
2 parents 64fe800 + 3815d3b commit 6522e83
Show file tree
Hide file tree
Showing 22 changed files with 807 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ public static AuthenticationMechanismException fromException(final Exception sou
return copyContents(source, new AuthenticationMechanismException(source.getMessage(), source.getCause()));
}

/**
* Copies the stack trace and suppressed exceptions from a source exception to a specified throwable.
*
* @param source the source exception from which the stack trace and suppressed exceptions should be copied.
* @param throwable the throwable to which the contents should be copied.
* @param <T> the type of throwable to which the contents should be copied.
* @return the throwable that was passed in as a parameter, with the contents copied from the source exception.
*/
private static <T extends Throwable> T copyContents(final Exception source, final T throwable) {
throwable.setStackTrace(source.getStackTrace());
final Throwable[] suppressed = source.getSuppressed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ private MechanismUtil() {}
* @param providers the security providers to use with the {@link PasswordFactory}
* @param <S> the password type
* @return the password
* @throws AuthenticationMechanismException if there is an error retrieving the password
*/
@Deprecated
public static <S extends Password> S getPasswordCredential(String userName, CallbackHandler callbackHandler, Class<S> passwordType, String passwordAlgorithm, AlgorithmParameterSpec matchParameters, AlgorithmParameterSpec generateParameters, Supplier<Provider[]> providers) throws AuthenticationMechanismException {
Expand All @@ -78,6 +79,7 @@ public static <S extends Password> S getPasswordCredential(String userName, Call
* @param <S> the password type
* @param log mechanism specific logger
* @return the password
* @throws AuthenticationMechanismException if there is an error retrieving the password
*/
@Deprecated
public static <S extends Password> S getPasswordCredential(String userName, CallbackHandler callbackHandler, Class<S> passwordType, String passwordAlgorithm, AlgorithmParameterSpec matchParameters, AlgorithmParameterSpec generateParameters, Supplier<Provider[]> providers, ElytronMessages log) throws AuthenticationMechanismException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public enum ScramServerErrorCode {
private final String text;
private final byte[] messageBytes;

/**
* Creates an error code instance with a String representation and a byte array for error message.
*/
ScramServerErrorCode() {
text = name().replace('_', '-').toLowerCase(Locale.US);
final int length = text.length();
Expand All @@ -54,14 +57,29 @@ public enum ScramServerErrorCode {
messageBytes = msg;
}

/**
* Returns the String representation of the error code.
*
* @return String representation of the error code.
*/
public String getText() {
return text;
}

/**
* Returns the copy of the byte array representing the error message.
*
* @return copy of the byte array representing the error message.
*/
public byte[] getMessageBytes() {
return messageBytes.clone();
}

/**
* Returns the byte array representing the error message.
*
* @return the byte array representing the error message.
*/
byte[] getRawMessageBytes() {
return messageBytes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public String getMessage() {
return super.getMessage() + ": " + error.getText();
}

/**
* Returns the error code of the exception.
*
* @return the error code of the exception.
*/
public ScramServerErrorCode getError() {
return error;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ private MechanismUtil() {}
* @param <S> the password type
* @param log mechanism specific logger
* @return the password
* @throws AuthenticationMechanismException if there is an error retrieving the password
*/
public static <S extends Password> S getPasswordCredential(String userName, CallbackHandler callbackHandler, Class<S> passwordType, String passwordAlgorithm, AlgorithmParameterSpec matchParameters, AlgorithmParameterSpec generateParameters, Supplier<Provider[]> providers, ElytronMessages log) throws AuthenticationMechanismException {
Assert.checkNotNullParam("userName", userName);
Expand Down Expand Up @@ -168,6 +169,7 @@ public static void handleCallbacks(ElytronMessages log, CallbackHandler callback
* @param scope the HTTP scope to store computed value (must not be {@code null})
* @param key the key to retrieve (must not be {@code null})
* @param mappingFunction the function to apply to acquire the value (must not be {@code null})
* @param <R> the type of returned value
* @return the stored or new value (not {@code null})
*/
public static <R> R computeIfAbsent(HttpScope scope, String key, Function<String, R> mappingFunction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.wildfly.common.bytes.ByteStringBuilder;

/**
* Utility class used to convert string to quoted strings
* Utility class used to convert string to quoted strings.
*
* @author <a href="mailto:[email protected]">Peter Skopek</a>
*
Expand All @@ -33,6 +33,12 @@ public class DigestQuote {
private DigestQuote() {
}

/**
* Checks if a given character needs to be quoted.
*
* @param ch the character to check.
* @return {@code true} if the character needs to be quoted, {@code false} otherwise.
*/
private static boolean quoteNeeded(char ch) {
return
ch == '"' || // escape char
Expand All @@ -46,8 +52,8 @@ private static boolean quoteNeeded(char ch) {
/**
* Creates new String quoted by SASL rules.
*
* @param inputStr String to be quoted
* @return
* @param inputStr String to be quoted.
* @return new String with quoted characters.
*/
public static String quote(String inputStr) {
int len = inputStr.length();
Expand All @@ -64,6 +70,12 @@ public static String quote(String inputStr) {
return sb.toString();
}

/**
* Creates new Array quoted by SASL rules.
*
* @param input Byte array to be quoted.
* @return new byte array with quoted bytes.
*/
public static byte[] quote(byte[] input) {
ByteStringBuilder bsb = new ByteStringBuilder();
for (int i = 0; i < input.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
import java.util.HashMap;
import java.util.function.Supplier;

import javax.security.sasl.SaslException;

import org.wildfly.common.bytes.ByteStringBuilder;
import org.wildfly.security.mechanism._private.ElytronMessages;
import org.wildfly.security.mechanism.AuthenticationMechanismException;
Expand All @@ -52,9 +50,12 @@ public class DigestUtil {
/**
* Client side method to parse challenge sent by server.
*
* @param challenge
* @return
* @throws AuthenticationMechanismException
* @param challenge the byte array representing the authentication challenge to be parsed.
* @param charset the charset to decide which whitespace separator is used.
* @param multiRealm {@code true} if there are multiple realms in the challenge, {@code false} otherwise
* @param log the logger to use.
* @return A new HashMap representing response for the parsed challenge
* @throws AuthenticationMechanismException if there is an error parsing the challenge
*/
public static HashMap<String, byte[]> parseResponse(byte [] challenge, Charset charset, boolean multiRealm, ElytronMessages log) throws AuthenticationMechanismException {

Expand Down Expand Up @@ -170,6 +171,15 @@ else if (expectSeparator) {
return response;
}

/**
* Adds a key-value pair to a HashMap representing a parsed challenge.
*
* @param response the HashMap to add the key-value pair to.
* @param keyBuilder the StringBuilder containing the key.
* @param valueBuilder the ByteStringBuilder containing the value.
* @param realmNumber the current number of realms in the parsed challenge.
* @return the updated number of realms in the parsed challenge.
*/
private static int addToParsedChallenge(HashMap<String, byte[]> response, StringBuilder keyBuilder, ByteStringBuilder valueBuilder, int realmNumber) {
String k = keyBuilder.toString();
byte[] v = valueBuilder.toArray();
Expand All @@ -183,6 +193,13 @@ private static int addToParsedChallenge(HashMap<String, byte[]> response, String
return realmNumber;
}

/**
* Finds the next non-whitespace character in a byte array.
*
* @param buffer the byte array to search in.
* @param startPoint the starting point in the buffer to begin the search.
* @return the index of the next non-whitespace character.
*/
private static int skipWhiteSpace(byte[] buffer, int startPoint) {
int i = startPoint;
while (i < buffer.length && isWhiteSpace(buffer[i])) {
Expand All @@ -191,6 +208,12 @@ private static int skipWhiteSpace(byte[] buffer, int startPoint) {
return i;
}

/**
* Checks if a given byte is a whitespace character.
*
* @param b the byte to check.
* @return {@code true} if the byte is a whitespace character, {@code false} otherwise.
*/
private static boolean isWhiteSpace(byte b) {
if (b == 13) // CR
return true;
Expand All @@ -204,6 +227,15 @@ else if (b == 32) // SPACE
return false;
}

/**
* Digests the concatenated username, realm and password.
*
* @param messageDigest the message digest algorithm to use when computing the digest.
* @param username the username to use when concatenating.
* @param realm the realm to use when concatenating.
* @param password the password in the form of a char array to use when concatenating.
* @return byte array of the digested password.
*/
public static byte[] userRealmPasswordDigest(MessageDigest messageDigest, String username, String realm, char[] password) {
CharsetEncoder latin1Encoder = StandardCharsets.ISO_8859_1.newEncoder();
latin1Encoder.reset();
Expand Down Expand Up @@ -232,10 +264,13 @@ public static byte[] userRealmPasswordDigest(MessageDigest messageDigest, String
}

/**
* Get array of password chars from TwoWayPassword
* Get array of password chars from TwoWayPassword.
*
* @return
* @throws SaslException
* @param password the TwoWayPassword that needs to be processed.
* @param providers the supplier for the providers to be used for processing.
* @param log the logger to use.
* @throws AuthenticationMechanismException if there is an error retrieving the encoded password.
* @return encoded password in the form of a char array.
*/
public static char[] getTwoWayPasswordChars(TwoWayPassword password, Supplier<Provider[]> providers, ElytronMessages log) throws AuthenticationMechanismException {
if (password == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
import static org.wildfly.security.mechanism.digest.DigestUtil.userRealmPasswordDigest;

/**
* Utility class used to obtain username+realm+password using SASL/HTTP mechanism callbacks
* Utility class used to obtain username+realm+password using SASL/HTTP mechanism callbacks.
*
* @author <a href="mailto:[email protected]">Jan Kalina</a>
*/
Expand All @@ -67,6 +67,20 @@ public class PasswordDigestObtainer {
private RealmCallback realmCallback;
private NameCallback nameCallback;

/**
* Constructs a new {@code PasswordDigestObtainer} instance.
*
* @param callbackHandler the callbackHandler to handle the callbacks required to obtain the username and password.
* @param defaultUsername the default username to use if a callback is not provided.
* @param defaultRealm the default realm to use if a callback is not provided.
* @param log the logger to use.
* @param credentialAlgorithm the name of the algorithm for obtaining the credential.
* @param messageDigest the {@link MessageDigest} used for digesting the password.
* @param passwordFactoryProviders the supplier of the providers to use when creating a {@code PasswordFactory} instance.
* @param realms the realms to check for a user and password.
* @param readOnlyRealmUsername {@code true} if the username passed in the callback can be modified, {@code false} otherwise.
* @param skipRealmCallbacks {@code true} if realm callbacks should be skipped, {@code false} otherwise.
*/
public PasswordDigestObtainer(CallbackHandler callbackHandler, String defaultUsername, String defaultRealm,
ElytronMessages log, String credentialAlgorithm, MessageDigest messageDigest,
Supplier<Provider[]> passwordFactoryProviders, String[] realms,
Expand All @@ -83,14 +97,30 @@ public PasswordDigestObtainer(CallbackHandler callbackHandler, String defaultUse
this.skipRealmCallbacks = skipRealmCallbacks;
}

/**
* Returns the username obtained from callback or the default one.
*
* @return the username obtained from callback or the default one.
*/
public String getUsername() {
return username;
}

/**
* Returns the realm obtained from callback or the default one.
*
* @return the realm obtained from callback or the default one.
*/
public String getRealm() {
return realm;
}

/**
* Handles callbacks for user and password information.
*
* @return the salted password.
* @throws AuthenticationMechanismException if the callback handler does not support credential acquisition.
*/
public byte[] handleUserRealmPasswordCallbacks() throws AuthenticationMechanismException {

realmChoiceCallBack = skipRealmCallbacks || realms == null || realms.length <= 1 ? null :
Expand All @@ -115,6 +145,12 @@ public byte[] handleUserRealmPasswordCallbacks() throws AuthenticationMechanismE
throw log.mechCallbackHandlerDoesNotSupportCredentialAcquisition(null);
}

/**
* Obtains the pre-digested salted password for the {@code username} in the {@code realm}.
*
* @return the pre-digested salted password if obtained, {@code null} otherwise.
* @throws AuthenticationMechanismException if an exception occurs while handling the callbacks.
*/
private byte[] getPredigestedSaltedPassword() throws AuthenticationMechanismException {
if (realmChoiceCallBack != null) {
try {
Expand Down Expand Up @@ -180,6 +216,12 @@ private byte[] getPredigestedSaltedPassword() throws AuthenticationMechanismExce
return null;
}

/**
* Obtains the salted password from a two-way callback.
*
* @return the byte array of the salted password if obtained, {@code null} otherwise.
* @throws AuthenticationMechanismException if an error occurs during the process of handling callbacks or obtaining the password.
*/
private byte[] getSaltedPasswordFromTwoWay() throws AuthenticationMechanismException {
if (realmChoiceCallBack != null) {
try {
Expand Down Expand Up @@ -253,6 +295,12 @@ private byte[] getSaltedPasswordFromTwoWay() throws AuthenticationMechanismExcep
return null;
}

/**
* Obtains the salted password from a password callback.
*
* @return the byte array of the salted password.
* @throws AuthenticationMechanismException if an error occurs during the process of handling callbacks or obtaining the password.
*/
private byte[] getSaltedPasswordFromPasswordCallback() throws AuthenticationMechanismException {
PasswordCallback passwordCallback = new PasswordCallback("User password: ", false);

Expand Down
Loading

0 comments on commit 6522e83

Please sign in to comment.