protected void doSenderAction()

in ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java [71:265]


    protected void doSenderAction(
            Document doc,
            RequestData reqData,
            List<HandlerAction> actions,
            boolean isRequest
    ) throws WSSecurityException {

        WSSConfig wssConfig = reqData.getWssConfig();
        if (wssConfig == null) {
            wssConfig = WSSConfig.getNewInstance();
            reqData.setWssConfig(wssConfig);
        }

        if (reqData.getWsDocInfo() == null) {
            WSDocInfo wsDocInfo = new WSDocInfo(doc);
            reqData.setWsDocInfo(wsDocInfo);
        }

        Object mc = reqData.getMsgContext();
        reqData.setEncodePasswords(
            decodeBooleanConfigValue(mc, WSHandlerConstants.USE_ENCODED_PASSWORDS, false)
        );
        reqData.setPrecisionInMilliSeconds(
            decodeBooleanConfigValue(mc, WSHandlerConstants.TIMESTAMP_PRECISION, true)
        );
        reqData.setAddInclusivePrefixes(
            decodeBooleanConfigValue(mc, WSHandlerConstants.ADD_INCLUSIVE_PREFIXES, true)
        );
        reqData.setEnableSignatureConfirmation(
            decodeBooleanConfigValue(mc, WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, false)
        );
        reqData.setTimeStampTTL(decodeTimeToLive(reqData, true));

        String actor = getString(WSHandlerConstants.ACTOR, mc);
        reqData.setActor(actor);

        boolean mu = decodeBooleanConfigValue(mc, WSHandlerConstants.MUST_UNDERSTAND, true);
        WSSecHeader secHeader = new WSSecHeader(actor, mu, doc);
        secHeader.insertSecurityHeader();
        reqData.setSecHeader(secHeader);
        reqData.setSoapConstants(WSSecurityUtil.getSOAPConstants(doc.getDocumentElement()));

        // Load CallbackHandler
        if (reqData.getCallbackHandler() == null) {
            CallbackHandler passwordCallbackHandler = getPasswordCallbackHandler(reqData);
            reqData.setCallbackHandler(passwordCallbackHandler);
        }

        if (!reqData.isStoreBytesInAttachment()) {
            boolean storeBytesInAttachment =
                decodeBooleanConfigValue(mc, WSHandlerConstants.STORE_BYTES_IN_ATTACHMENT, false);
            reqData.setStoreBytesInAttachment(storeBytesInAttachment);
        }

        // Perform configuration
        boolean encryptionFound = false;
        for (HandlerAction actionToDo : actions) {
            if (actionToDo.getAction() == WSConstants.SC) {
                reqData.setEnableSignatureConfirmation(true);
            } else if ((actionToDo.getAction() == WSConstants.UT
                || actionToDo.getAction() == WSConstants.UT_NOPASSWORD)
                && actionToDo.getActionToken() == null) {
                decodeUTParameter(reqData);
                if (actionToDo.getAction() == WSConstants.UT_NOPASSWORD) {
                    reqData.setPwType(null);
                }
            } else if (actionToDo.getAction() == WSConstants.UT_SIGN
                && actionToDo.getActionToken() == null) {
                decodeUTParameter(reqData);
                decodeSignatureParameter(reqData);
            } else if ((actionToDo.getAction() == WSConstants.SIGN
                || actionToDo.getAction() == WSConstants.DKT_SIGN)
                && actionToDo.getActionToken() == null) {
                SignatureActionToken actionToken = reqData.getSignatureToken();
                if (actionToken == null) {
                    actionToken = new SignatureActionToken();
                    reqData.setSignatureToken(actionToken);
                }
                if (actionToken.getCrypto() == null) {
                    actionToken.setCrypto(loadSignatureCrypto(reqData));
                }
                decodeSignatureParameter(reqData);
                if (encryptionFound && reqData.isStoreBytesInAttachment()) {
                    LOG.warn("Turning off storeBytesInAttachment as we have encryption before signature."
                             + " The danger here is that the actual encryption bytes will not be signed");
                    reqData.setStoreBytesInAttachment(false);
                }
            } else if (actionToDo.getAction() == WSConstants.ST_SIGNED
                && actionToDo.getActionToken() == null) {
                decodeSignatureParameter(reqData);
            } else if ((actionToDo.getAction() == WSConstants.ENCR
                || actionToDo.getAction() == WSConstants.DKT_ENCR)
                && actionToDo.getActionToken() == null) {
                encryptionFound = true;
                EncryptionActionToken actionToken = reqData.getEncryptionToken();
                if (actionToken == null) {
                    actionToken = new EncryptionActionToken();
                    reqData.setEncryptionToken(actionToken);
                }
                if (actionToken.getCrypto() == null) {
                    actionToken.setCrypto(loadEncryptionCrypto(reqData));
                }
                decodeEncryptionParameter(reqData);
            }
        }

        /*
         * If after all the parsing no Signature parts defined, set here a
         * default set. This is necessary because we add SignatureConfirmation
         * and therefore the default (Body) must be set here. The default setting
         * in WSSignEnvelope doesn't work because the vector is not empty anymore.
         */
        SignatureActionToken signatureToken = reqData.getSignatureToken();
        if (signatureToken == null) {
            signatureToken = new SignatureActionToken();
            reqData.setSignatureToken(signatureToken);
        }
        if (signatureToken.getParts().isEmpty()) {
            signatureToken.getParts().add(WSSecurityUtil.getDefaultEncryptionPart(doc));
        }
        /*
         * If SignatureConfirmation is enabled and this is a response then
         * insert SignatureConfirmation elements, note their wsu:id in the signature
         * parts. They will be signed automatically during a (probably) defined
         * SIGN action.
         */
        if (reqData.isEnableSignatureConfirmation() && !isRequest) {
            String done =
                (String)getProperty(reqData.getMsgContext(), WSHandlerConstants.SIG_CONF_DONE);
            if (done == null) {
                wssConfig.getAction(WSConstants.SC).execute(this, null, reqData);
            }
        }

        // See if the Signature and Timestamp actions (in that order) are defined, and if
        // the Timestamp is to be signed. In this case we need to swap the actions, as the
        // Timestamp must appear in the security header first for signature creation to work.
        List<HandlerAction> actionsToPerform = actions;
        HandlerAction signingAction = getSignatureActionThatSignsATimestamp(actions, reqData);

        if (signingAction != null) {
            actionsToPerform = new ArrayList<>(actions);

            // Find TimestampAction
            int timestampIndex = -1;
            for (int i = 0; i < actionsToPerform.size(); i++) {
                if (actionsToPerform.get(i).getAction() == WSConstants.TS) {
                    timestampIndex = i;
                    break;
                }
            }

            int signatureIndex = actionsToPerform.indexOf(signingAction);
            if (timestampIndex >= 0) {
                actionsToPerform.set(signatureIndex, actionsToPerform.get(timestampIndex));
                actionsToPerform.set(timestampIndex, signingAction);
            }
            reqData.setAppendSignatureAfterTimestamp(true);
            reqData.setOriginalSignatureActionPosition(signatureIndex);
        }

        /*
         * Here we have all necessary information to perform the requested
         * action(s).
         */
        for (HandlerAction actionToDo : actionsToPerform) {
            LOG.debug("Performing Action: {}", actionToDo.getAction());

            if (WSConstants.NO_SECURITY != actionToDo.getAction()) {
                wssConfig.getAction(actionToDo.getAction()).execute(
                    this, actionToDo.getActionToken(), reqData);
            }
        }

        /*
         * If this is a request then store all signature values. Add ours to
         * already gathered values because of chained handlers, e.g. for
         * other actors.
         */
        if (reqData.isEnableSignatureConfirmation()
            && isRequest && !reqData.getSignatureValues().isEmpty()) {
            @SuppressWarnings("unchecked")
            Set<Integer> savedSignatures =
                (Set<Integer>)getProperty(reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV);
            if (savedSignatures == null) {
                savedSignatures = new HashSet<>();
                setProperty(
                    reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV, savedSignatures
                );
            }
            for (byte[] signatureValue : reqData.getSignatureValues()) {
                savedSignatures.add(Arrays.hashCode(signatureValue));
            }
        }
    }