Github user necouchman commented on a diff in the pull request: https://github.com/apache/incubator-guacamole-client/pull/183#discussion_r142027025 --- Diff: extensions/guacamole-auth-cas/src/main/java/org/apache/guacamole/auth/cas/ticket/TicketValidationService.java --- @@ -70,14 +85,93 @@ public String processUsername(String ticket) throws GuacamoleException { try { String confRedirectURI = confService.getRedirectURI(); Assertion a = validator.validate(ticket, confRedirectURI); - principal = a.getPrincipal(); + AttributePrincipal principal = a.getPrincipal(); + + // Retrieve username and set the credentials. + String username = principal.getName(); + if (username != null) + credentials.setUsername(username); + + // Retrieve password, attempt decryption, and set credentials. + Object credObj = principal.getAttributes().get("credential"); + if (credObj != null) { + String clearPass = decryptPassword(credObj.toString()); + if (clearPass != null && !clearPass.isEmpty()) + credentials.setPassword(clearPass); + } + + return username; + } catch (TicketValidationException e) { throw new GuacamoleException("Ticket validation failed.", e); } - // Return the principal name as the username. - return principal.getName(); + } + + /** + * Takes an encrypted string representing a password provided by + * the CAS ClearPass service and decrypts it using the private + * key configured for this extension. Returns null if it is + * unable to decrypt the password. + * + * @param encryptedPassword + * A string with the encrypted password provided by the + * CAS service. + * + * @return + * The decrypted password, or null if it is unable to + * decrypt the password. + * + * @throws GuacamoleException + * If unable to get Guacamole configuration data + */ + private final String decryptPassword(String encryptedPassword) + throws GuacamoleException { + + // If we get nothing, we return nothing. + if (encryptedPassword == null || encryptedPassword.isEmpty()) { + logger.warn("No or empty encrypted password, no password will be available."); + return null; + } + + final PrivateKey clearpassKey = confService.getClearpassKey(); + if (clearpassKey == null) { + logger.warn("No private key available to decrypt password."); + return null; + } + + try { + + final Cipher cipher = Cipher.getInstance(clearpassKey.getAlgorithm()); + + if (cipher == null) + throw new GuacamoleServerException("Failed to initialize cipher object with private key."); + + // Initialize the Cipher in decrypt mode. + cipher.init(Cipher.DECRYPT_MODE, clearpassKey); + + // Decode and decrypt, and return a new string. + final byte[] pass64 = DatatypeConverter.parseBase64Binary(encryptedPassword); + final byte[] cipherData = cipher.doFinal(pass64); + return new String(cipherData); --- End diff -- I'll have to dig into the CAS side and see. Is there a preferred way to convert byte[] data to a String in Java that is considered production-safe?
---