@Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { log.info("handle({})", callbacks); WSPasswordCallback pwdCallback = (WSPasswordCallback) callbacks[0]; log.debug("identifier: " + pwdCallback.getIdentifier()); log.debug("usage: " + pwdCallback.getUsage()); int usage = pwdCallback.getUsage(); if (usage == WSPasswordCallback.USERNAME_TOKEN) { String password = pwdCallback.getPassword(); Authentication authentication = new UsernamePasswordAuthenticationToken(pwdCallback.getIdentifier(), password); authentication = authenticationManager.authenticate(authentication); SecurityContextHolder.getContext().setAuthentication(authentication); // Return the password to the caller pwdCallback.setPassword(password); } }
/** * Method handle * * @param callbacks * @throws java.io.IOException * @throws javax.security.auth.callback.UnsupportedCallbackException */ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof WSPasswordCallback) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; /* * This usage type is used only in case we received a * username token with a secret of type PasswordText or * an unknown secret type. * * This case the WSPasswordCallback object contains the * identifier (aka username), the secret we received, and * the secret type string to identify the type. * * Here we perform only a very simple check. */ if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) { if (pc.getIdentifier().equals("Ron") && pc.getPassword().equals("noR")) { return; } if (pc.getIdentifier().equals("joe") && pc.getPassword().equals("eoj")) { return; } if (pc.getPassword().equals("sirhC")) { return; } throw new UnsupportedCallbackException(callbacks[i], "check failed"); } /* * here call a function/method to lookup the secret for * the given identifier (e.g. a user name or keystore alias) * e.g.: pc.setSecret(passStore.getSecret(pc.getIdentfifier)) * for Testing we supply a fixed name here. */ if (pc.getUsage() == WSPasswordCallback.KEY_NAME) { pc.setKey(key); } else if (pc.getIdentifier().equals("alice")) { pc.setPassword("password"); } else if (pc.getIdentifier().equals("bob")) { pc.setPassword("password"); } else if (pc.getIdentifier().equals("Ron")) { pc.setPassword("noR"); } else if (pc.getIdentifier().equals("joe")) { pc.setPassword("eoj"); } else if (pc.getIdentifier().equals("ip")) { pc.setPassword("password"); } else { pc.setPassword("sirhC"); } } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } }
public ArrayList handleEncryptedKey( Element xencEncryptedKey, CallbackHandler cb, Crypto crypto, PrivateKey privateKey) throws WSSecurityException { long t0 = 0, t1 = 0, t2 = 0; if (tlog.isDebugEnabled()) { t0 = System.currentTimeMillis(); } // need to have it to find the encrypted data elements in the envelope Document doc = xencEncryptedKey.getOwnerDocument(); // lookup xenc:EncryptionMethod, get the Algorithm attribute to determine // how the key was encrypted. Then check if we support the algorithm Node tmpE = null; // short living Element used for lookups only tmpE = (Element) WSSecurityUtil.getDirectChild( (Node) xencEncryptedKey, "EncryptionMethod", WSConstants.ENC_NS); if (tmpE != null) { this.encryptedKeyTransportMethod = ((Element) tmpE).getAttribute("Algorithm"); } if (this.encryptedKeyTransportMethod == null) { throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM, "noEncAlgo"); } Cipher cipher = WSSecurityUtil.getCipherInstance(this.encryptedKeyTransportMethod); // // Well, we can decrypt the session (symmetric) key. Now lookup CipherValue, this is the // value of the encrypted session key (session key usually is a symmetrical key that encrypts // the referenced content). This is a 2-step lookup // Element xencCipherValue = null; tmpE = (Element) WSSecurityUtil.getDirectChild( (Node) xencEncryptedKey, "CipherData", WSConstants.ENC_NS); if (tmpE != null) { xencCipherValue = (Element) WSSecurityUtil.getDirectChild(tmpE, "CipherValue", WSConstants.ENC_NS); } if (xencCipherValue == null) { throw new WSSecurityException(WSSecurityException.INVALID_SECURITY, "noCipher"); } if (privateKey == null) { Element keyInfo = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey, "KeyInfo", WSConstants.SIG_NS); String alias; if (keyInfo != null) { Element secRefToken = (Element) WSSecurityUtil.getDirectChild( keyInfo, "SecurityTokenReference", WSConstants.WSSE_NS); // // EncryptedKey must a a STR as child of KeyInfo, KeyName // valid only for EncryptedData // // if (secRefToken == null) { // secRefToken = (Element) WSSecurityUtil.getDirectChild(keyInfo, // "KeyName", WSConstants.SIG_NS); // } if (secRefToken == null) { throw new WSSecurityException(WSSecurityException.INVALID_SECURITY, "noSecTokRef"); } SecurityTokenReference secRef = new SecurityTokenReference(secRefToken); // // Well, at this point there are several ways to get the key. // Try to handle all of them :-). // alias = null; // // handle X509IssuerSerial here. First check if all elements are available, // get the appropriate data, check if all data is available. // If all is ok up to that point, look up the certificate alias according // to issuer name and serial number. // This method is recommended by OASIS WS-S specification, X509 profile // if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) { alias = secRef.getX509IssuerSerialAlias(crypto); if (log.isDebugEnabled()) { log.debug("X509IssuerSerial alias: " + alias); } } // // If wsse:KeyIdentifier found, then the public key of the attached cert was used to // encrypt the session (symmetric) key that encrypts the data. Extract the certificate // using the BinarySecurity token (was enhanced to handle KeyIdentifier too). // This method is _not_ recommended by OASIS WS-S specification, X509 profile // else if (secRef.containsKeyIdentifier()) { X509Certificate[] certs = null; if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())) { Element token = secRef.getKeyIdentifierTokenElement(doc, docInfo, cb); if (crypto == null) { throw new WSSecurityException(WSSecurityException.FAILURE, "noSigCryptoFile"); } SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(token, crypto, cb); certs = samlKi.getCerts(); } else if (WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals( secRef.getKeyIdentifierValueType())) { Element token = secRef.getKeyIdentifierTokenElement(doc, docInfo, cb); if (crypto == null) { throw new WSSecurityException(0, "noSigCryptoFile"); } SAML2KeyInfo samlKi = SAML2Util.getSAML2KeyInfo(token, crypto, cb); certs = samlKi.getCerts(); } else { certs = secRef.getKeyIdentifier(crypto); } if (certs == null || certs.length < 1 || certs[0] == null) { throw new WSSecurityException( WSSecurityException.FAILURE, "noCertsFound", new Object[] {"decryption (KeyId)"}); } // // Here we have the certificate. Now find the alias for it. Needed to identify // the private key associated with this certificate // alias = crypto.getAliasForX509Cert(certs[0]); cert = certs[0]; if (log.isDebugEnabled()) { log.debug("cert: " + certs[0]); log.debug("KeyIdentifier Alias: " + alias); } } else if (secRef.containsReference()) { Element bstElement = secRef.getTokenElement(doc, null, cb); // at this point ... check token type: Binary QName el = new QName(bstElement.getNamespaceURI(), bstElement.getLocalName()); if (el.equals(WSSecurityEngine.binaryToken)) { X509Security token = new X509Security(bstElement); String value = bstElement.getAttribute(WSSecurityEngine.VALUE_TYPE); if (!X509Security.X509_V3_TYPE.equals(value) || (token == null)) { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "unsupportedBinaryTokenType", new Object[] {"for decryption (BST)"}); } cert = token.getX509Certificate(crypto); if (cert == null) { throw new WSSecurityException( WSSecurityException.FAILURE, "noCertsFound", new Object[] {"decryption"}); } // // Here we have the certificate. Now find the alias for it. Needed to identify // the private key associated with this certificate // alias = crypto.getAliasForX509Cert(cert); if (log.isDebugEnabled()) { log.debug("BST Alias: " + alias); } } else { throw new WSSecurityException( WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "unsupportedBinaryTokenType", null); } // // The following code is somewhat strange: the called crypto method gets // the keyname and searches for a certificate with an issuer's name that is // equal to this keyname. No serialnumber is used - IMHO this does // not identifies a certificate. In addition neither the WSS4J encryption // nor signature methods use this way to identify a certificate. Because of that // the next lines of code are disabled. // // } else if (secRef.containsKeyName()) { // alias = crypto.getAliasForX509Cert(secRef.getKeyNameValue()); // if (log.isDebugEnabled()) { // log.debug("KeyName alias: " + alias); // } } else { throw new WSSecurityException(WSSecurityException.INVALID_SECURITY, "unsupportedKeyId"); } } else if (crypto.getDefaultX509Alias() != null) { alias = crypto.getDefaultX509Alias(); } else { throw new WSSecurityException(WSSecurityException.INVALID_SECURITY, "noKeyinfo"); } // // At this point we have all information necessary to decrypt the session // key: // - the Cipher object intialized with the correct methods // - The data that holds the encrypted session key // - the alias name for the private key // // Now use the callback here to get password that enables // us to read the private key // WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.DECRYPT); try { Callback[] callbacks = new Callback[] {pwCb}; cb.handle(callbacks); } catch (IOException e) { throw new WSSecurityException( WSSecurityException.FAILURE, "noPassword", new Object[] {alias}, e); } catch (UnsupportedCallbackException e) { throw new WSSecurityException( WSSecurityException.FAILURE, "noPassword", new Object[] {alias}, e); } String password = pwCb.getPassword(); if (password == null) { throw new WSSecurityException( WSSecurityException.FAILURE, "noPassword", new Object[] {alias}); } try { privateKey = crypto.getPrivateKey(alias, password); } catch (Exception e) { throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e); } } try { cipher.init(Cipher.DECRYPT_MODE, privateKey); } catch (Exception e1) { throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e1); } try { encryptedEphemeralKey = getDecodedBase64EncodedData(xencCipherValue); decryptedBytes = cipher.doFinal(encryptedEphemeralKey); } catch (IllegalStateException e2) { throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e2); } catch (Exception e2) { decryptedBytes = getRandomKey( getDataRefURIs(xencCipherValue), xencEncryptedKey.getOwnerDocument(), docInfo); } if (tlog.isDebugEnabled()) { t1 = System.currentTimeMillis(); } // At this point we have the decrypted session (symmetric) key. According // to W3C XML-Enc this key is used to decrypt _any_ references contained in // the reference list // Now lookup the references that are encrypted with this key // Element refList = (Element) WSSecurityUtil.getDirectChild( (Node) xencEncryptedKey, "ReferenceList", WSConstants.ENC_NS); ArrayList dataRefs = new ArrayList(); if (refList != null) { for (tmpE = refList.getFirstChild(); tmpE != null; tmpE = tmpE.getNextSibling()) { if (tmpE.getNodeType() != Node.ELEMENT_NODE) { continue; } if (!tmpE.getNamespaceURI().equals(WSConstants.ENC_NS)) { continue; } if (tmpE.getLocalName().equals("DataReference")) { String dataRefURI = ((Element) tmpE).getAttribute("URI"); if (dataRefURI.charAt(0) == '#') { dataRefURI = dataRefURI.substring(1); } WSDataRef dataRef = decryptDataRef(doc, dataRefURI, decryptedBytes); dataRefs.add(dataRef); } } return dataRefs; } if (tlog.isDebugEnabled()) { t2 = System.currentTimeMillis(); tlog.debug( "XMLDecrypt: total= " + (t2 - t0) + ", get-sym-key= " + (t1 - t0) + ", decrypt= " + (t2 - t1)); } return null; }