mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUACAMOLE-839: Generate case-insensitive nonce values that can safely be used in domains.
This commit is contained in:
		| @@ -21,6 +21,7 @@ package org.apache.guacamole.auth.sso; | ||||
|  | ||||
| import com.google.common.io.BaseEncoding; | ||||
| import com.google.inject.Singleton; | ||||
| import java.math.BigInteger; | ||||
| import java.security.SecureRandom; | ||||
|  | ||||
| /** | ||||
| @@ -40,7 +41,8 @@ public class IdentifierGenerator { | ||||
|     /** | ||||
|      * Generates a unique and unpredictable identifier. Each identifier is at | ||||
|      * least 256-bit and produced using a cryptographically-secure random | ||||
|      * number generator. | ||||
|      * number generator. The identifier may contain characters that differ only | ||||
|      * in case. | ||||
|      * | ||||
|      * @return | ||||
|      *     A unique and unpredictable identifier with at least 256 bits of | ||||
| @@ -53,7 +55,8 @@ public class IdentifierGenerator { | ||||
|     /** | ||||
|      * Generates a unique and unpredictable identifier having at least the | ||||
|      * given number of bits of entropy. The resulting identifier may have more | ||||
|      * than the number of bits required. | ||||
|      * than the number of bits required. The identifier may contain characters | ||||
|      * that differ only in case. | ||||
|      * | ||||
|      * @param minBits | ||||
|      *     The number of bits of entropy that the identifier should contain. | ||||
| @@ -63,9 +66,41 @@ public class IdentifierGenerator { | ||||
|      *     of bits of entropy. | ||||
|      */ | ||||
|     public String generateIdentifier(int minBits) { | ||||
|         byte[] bytes = new byte[(minBits + 23) / 24 * 3]; // Round up to nearest multiple of 3 bytes, as base64 encodes blocks of 3 bytes at a time | ||||
|         secureRandom.nextBytes(bytes); | ||||
|         return BaseEncoding.base64().encode(bytes); | ||||
|         return generateIdentifier(minBits, true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generates a unique and unpredictable identifier having at least the | ||||
|      * given number of bits of entropy. The resulting identifier may have more | ||||
|      * than the number of bits required. The identifier may contain characters | ||||
|      * that differ only in case. | ||||
|      * | ||||
|      * @param minBits | ||||
|      *     The number of bits of entropy that the identifier should contain. | ||||
|      * | ||||
|      * @param caseSensitive | ||||
|      *     Whether identifiers are permitted to contain characters that vary | ||||
|      *     by case. If false, all characters that may vary by case will be | ||||
|      *     lowercase, and the generated identifier will be longer. | ||||
|      * | ||||
|      * @return | ||||
|      *     A unique and unpredictable identifier with at least the given number | ||||
|      *     of bits of entropy. | ||||
|      */ | ||||
|     public String generateIdentifier(int minBits, boolean caseSensitive) { | ||||
|  | ||||
|         // Generate a base64 identifier if we're allowed to vary by case | ||||
|         if (caseSensitive) { | ||||
|             int minBytes = (minBits + 23) / 24 * 3; // Round up to nearest multiple of 3 bytes, as base64 encodes blocks of 3 bytes at a time | ||||
|             byte[] bytes = new byte[minBytes]; | ||||
|             secureRandom.nextBytes(bytes); | ||||
|             return BaseEncoding.base64().encode(bytes); | ||||
|         } | ||||
|  | ||||
|         // Generate base32 identifiers if we cannot vary by case | ||||
|         minBits = (minBits + 4) / 5 * 5; // Round up to nearest multiple of 5 bits, as base32 encodes 5 bits at a time | ||||
|         return new BigInteger(minBits, secureRandom).toString(32); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -22,11 +22,13 @@ package org.apache.guacamole.auth.sso; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Singleton; | ||||
| import java.util.Iterator; | ||||
| import java.util.Locale; | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
|  | ||||
| /** | ||||
|  * Service for generating and validating single-use random tokens (nonces). | ||||
|  * Each generated nonce is at least 128 bits and case-insensitive. | ||||
|  */ | ||||
| @Singleton | ||||
| public class NonceService { | ||||
| @@ -98,7 +100,8 @@ public class NonceService { | ||||
|      *     valid, in milliseconds. | ||||
|      * | ||||
|      * @return | ||||
|      *     A cryptographically-secure nonce value. | ||||
|      *     A cryptographically-secure nonce value. Generated nonces are at | ||||
|      *     least 128-bit and are case-insensitive. | ||||
|      */ | ||||
|     public String generate(long maxAge) { | ||||
|  | ||||
| @@ -106,7 +109,7 @@ public class NonceService { | ||||
|         sweepExpiredNonces(); | ||||
|  | ||||
|         // Generate and store nonce, along with expiration timestamp | ||||
|         String nonce = idGenerator.generateIdentifier(NONCE_BITS); | ||||
|         String nonce = idGenerator.generateIdentifier(NONCE_BITS, false); | ||||
|         nonces.put(nonce, System.currentTimeMillis() + maxAge); | ||||
|         return nonce; | ||||
|  | ||||
| @@ -119,7 +122,7 @@ public class NonceService { | ||||
|      * invalidates that nonce. | ||||
|      * | ||||
|      * @param nonce | ||||
|      *     The nonce value to test. | ||||
|      *     The nonce value to test. Comparisons are case-insensitive. | ||||
|      * | ||||
|      * @return | ||||
|      *     true if the provided nonce is valid, false otherwise. | ||||
| @@ -127,7 +130,7 @@ public class NonceService { | ||||
|     public boolean isValid(String nonce) { | ||||
|  | ||||
|         // Remove nonce, verifying whether it was present at all | ||||
|         Long expires = nonces.remove(nonce); | ||||
|         Long expires = nonces.remove(nonce.toLowerCase(Locale.US)); | ||||
|         if (expires == null) | ||||
|             return false; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user