Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.apache.guacamole.auth.json;

import com.google.common.io.BaseEncoding;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
Expand Down Expand Up @@ -73,7 +74,7 @@ public class CryptoService {
* HMAC signature itself as the IV. For our purposes, where the encrypted
* value becomes an authentication token, this is OK.
*/
private static final IvParameterSpec NULL_IV = new IvParameterSpec(new byte[] {
public static final IvParameterSpec NULL_IV = new IvParameterSpec(new byte[] {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
});
Expand Down Expand Up @@ -125,6 +126,9 @@ public SecretKey createSignatureKey(byte[] keyBytes) {
*
* @param cipherText
* The ciphertext to decrypt.
*
* @param ivStr
* The IV to use for decrypting the ciphertext.
*
* @return
* The plaintext which results from decrypting the ciphertext with the
Expand All @@ -133,13 +137,25 @@ public SecretKey createSignatureKey(byte[] keyBytes) {
* @throws GuacamoleException
* If any error at all occurs during decryption.
*/
public byte[] decrypt(Key key, byte[] cipherText) throws GuacamoleException {
public byte[] decrypt(Key key, byte[] cipherText, String ivStr)
throws GuacamoleException {

try {

// Use NULL_IV by default, but, if an IV has been provided as
// part of the request, use that, instead.
IvParameterSpec iv = NULL_IV;
if (ivStr != null && !ivStr.isEmpty()) {
byte[] ivBytes = BaseEncoding.base64().decode(ivStr);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can throw IllegalArgumentException for malformed ivStr base64, but that exception is not handled here. It propagates to UserDataService.fromCredentials(), where the existing catch (IllegalArgumentException) logs Submitted data is not proper base64, which is misleading when only iv is invalid. Maybe consider catching IllegalArgumentException here and rethrowing as GuacamoleServerException("Invalid IV provided.").

if (ivBytes.length == 16)
iv = new IvParameterSpec(ivBytes);
else
throw new GuacamoleServerException("Invalid IV provided.");
}

// Init cipher for descryption using secret key
Cipher cipher = Cipher.getInstance(DECRYPTION_CIPHER_NAME);
cipher.init(Cipher.DECRYPT_MODE, key, NULL_IV);
cipher.init(Cipher.DECRYPT_MODE, key, iv);

// Perform decryption
return cipher.doFinal(cipherText);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ public class UserDataService {
* HMAC/SHA-256.
*/
public static final String ENCRYPTED_DATA_PARAMETER = "data";

/**
* The name of the HTTP parameter from which the cryptographic IV should be
* read, if provided with the query. If this parameter is not provided, the
* {@link CryptoService#NULL_IV} will be used.
*/
public static final String ENCRYPTED_IV_PARAMETER = "iv";

/**
* Derives a new UserData object from the data contained within the given
Expand Down Expand Up @@ -129,14 +136,18 @@ public UserData fromCredentials(Credentials credentials) {
String base64 = credentials.getParameter(ENCRYPTED_DATA_PARAMETER);
if (base64 == null)
return null;

// Get the IV string from the credentials
String ivStr = credentials.getParameter(ENCRYPTED_IV_PARAMETER);

// Decrypt base64-encoded parameter
try {

// Decrypt using defined encryption key
byte[] decrypted = cryptoService.decrypt(
cryptoService.createEncryptionKey(confService.getSecretKey()),
BaseEncoding.base64().decode(base64)
BaseEncoding.base64().decode(base64),
ivStr
);

// Abort if decrypted value cannot possibly have a signature AND data
Expand Down