Search in sources :

Example 1 with XMLSecEvent

use of org.apache.xml.security.stax.ext.stax.XMLSecEvent in project santuario-java by apache.

the class AbstractDecryptInputProcessor method processEvent.

private XMLSecEvent processEvent(InputProcessorChain inputProcessorChain, boolean isSecurityHeaderEvent) throws XMLStreamException, XMLSecurityException {
    if (!tmpXmlEventList.isEmpty()) {
        return tmpXmlEventList.pollLast();
    }
    XMLSecEvent xmlSecEvent = isSecurityHeaderEvent ? inputProcessorChain.processHeaderEvent() : inputProcessorChain.processEvent();
    boolean encryptedHeader = false;
    if (xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT) {
        XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
        // otherwise replay it
        if (xmlSecStartElement.getName().equals(XMLSecurityConstants.TAG_wsse11_EncryptedHeader)) {
            xmlSecEvent = readAndBufferEncryptedHeader(inputProcessorChain, isSecurityHeaderEvent, xmlSecEvent);
            xmlSecStartElement = xmlSecEvent.asStartElement();
            encryptedHeader = true;
        }
        // check if the current start-element has the name EncryptedData and an Id attribute
        if (xmlSecStartElement.getName().equals(XMLSecurityConstants.TAG_xenc_EncryptedData)) {
            ReferenceType referenceType = null;
            if (references != null) {
                referenceType = matchesReferenceId(xmlSecStartElement);
                if (referenceType == null) {
                    // if the events were not for us (no matching reference-id the we have to replay the EncryptedHeader elements)
                    if (!tmpXmlEventList.isEmpty()) {
                        return tmpXmlEventList.pollLast();
                    }
                    return xmlSecEvent;
                }
                // duplicate id's are forbidden
                if (processedReferences.contains(referenceType)) {
                    throw new XMLSecurityException("signature.Verification.MultipleIDs");
                }
                processedReferences.add(referenceType);
            }
            tmpXmlEventList.clear();
            // the following LOGic reads the encryptedData structure and doesn't pass them further
            // through the chain
            InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
            EncryptedDataType encryptedDataType = parseEncryptedDataStructure(isSecurityHeaderEvent, xmlSecEvent, subInputProcessorChain);
            if (encryptedDataType.getId() == null) {
                encryptedDataType.setId(IDGenerator.generateID(null));
            }
            InboundSecurityToken inboundSecurityToken = getSecurityToken(inputProcessorChain, xmlSecStartElement, encryptedDataType);
            handleSecurityToken(inboundSecurityToken, inputProcessorChain.getSecurityContext(), encryptedDataType);
            final String algorithmURI = encryptedDataType.getEncryptionMethod().getAlgorithm();
            final int ivLength = JCEAlgorithmMapper.getIVLengthFromURI(algorithmURI) / 8;
            Cipher symCipher = getCipher(algorithmURI);
            if (encryptedDataType.getCipherData().getCipherReference() != null) {
                handleCipherReference(inputProcessorChain, encryptedDataType, symCipher, inboundSecurityToken);
                subInputProcessorChain.reset();
                return isSecurityHeaderEvent ? subInputProcessorChain.processHeaderEvent() : subInputProcessorChain.processEvent();
            }
            // create a new Thread for streaming decryption
            DecryptionThread decryptionThread = new DecryptionThread(subInputProcessorChain, isSecurityHeaderEvent);
            Key decryptionKey = inboundSecurityToken.getSecretKey(algorithmURI, XMLSecurityConstants.Enc, encryptedDataType.getId());
            decryptionKey = XMLSecurityUtils.prepareSecretKey(algorithmURI, decryptionKey.getEncoded());
            decryptionThread.setSecretKey(decryptionKey);
            decryptionThread.setSymmetricCipher(symCipher);
            decryptionThread.setIvLength(ivLength);
            XMLSecStartElement parentXMLSecStartElement = xmlSecStartElement.getParentXMLSecStartElement();
            if (encryptedHeader) {
                parentXMLSecStartElement = parentXMLSecStartElement.getParentXMLSecStartElement();
            }
            AbstractDecryptedEventReaderInputProcessor decryptedEventReaderInputProcessor = newDecryptedEventReaderInputProcessor(encryptedHeader, parentXMLSecStartElement, encryptedDataType, inboundSecurityToken, inputProcessorChain.getSecurityContext());
            // add the new created EventReader processor to the chain.
            inputProcessorChain.addProcessor(decryptedEventReaderInputProcessor);
            inputProcessorChain.getDocumentContext().setIsInEncryptedContent(inputProcessorChain.getProcessors().indexOf(decryptedEventReaderInputProcessor), decryptedEventReaderInputProcessor);
            // important: this must occur after setIsInEncryptedContent!
            if (SecurePart.Modifier.Content.getModifier().equals(encryptedDataType.getType())) {
                handleEncryptedContent(inputProcessorChain, xmlSecStartElement.getParentXMLSecStartElement(), inboundSecurityToken, encryptedDataType);
            }
            Thread thread = new Thread(decryptionThread);
            thread.setPriority(Thread.NORM_PRIORITY + 1);
            thread.setName("decryption thread");
            // when an exception in the decryption thread occurs, we want to forward them:
            thread.setUncaughtExceptionHandler(decryptedEventReaderInputProcessor);
            decryptedEventReaderInputProcessor.setDecryptionThread(thread);
            // we have to start the thread before we call decryptionThread.getPipedInputStream().
            // Otherwise we will end in a deadlock, because the StAX reader expects already data.
            // @See some lines below:
            LOG.debug("Starting decryption thread");
            thread.start();
            InputStream prologInputStream;
            InputStream epilogInputStream;
            try {
                prologInputStream = writeWrapperStartElement(xmlSecStartElement);
                epilogInputStream = writeWrapperEndElement();
            } catch (UnsupportedEncodingException e) {
                throw new XMLSecurityException(e);
            } catch (IOException e) {
                throw new XMLSecurityException(e);
            }
            InputStream decryptInputStream = decryptionThread.getPipedInputStream();
            decryptInputStream = applyTransforms(referenceType, decryptInputStream);
            // spec says (4.2): "The cleartext octet sequence obtained in step 3 is
            // interpreted as UTF-8 encoded character data."
            XMLStreamReader xmlStreamReader = inputProcessorChain.getSecurityContext().<XMLInputFactory>get(XMLSecurityConstants.XMLINPUTFACTORY).createXMLStreamReader(new MultiInputStream(prologInputStream, decryptInputStream, epilogInputStream), StandardCharsets.UTF_8.name());
            // forward to wrapper element
            forwardToWrapperElement(xmlStreamReader);
            decryptedEventReaderInputProcessor.setXmlStreamReader(xmlStreamReader);
            if (isSecurityHeaderEvent) {
                return decryptedEventReaderInputProcessor.processNextHeaderEvent(inputProcessorChain);
            } else {
                return decryptedEventReaderInputProcessor.processNextEvent(inputProcessorChain);
            }
        }
    }
    return xmlSecEvent;
}
Also used : XMLStreamReader(javax.xml.stream.XMLStreamReader) EncryptedDataType(org.apache.xml.security.binding.xmlenc.EncryptedDataType) UnsyncByteArrayInputStream(org.apache.xml.security.utils.UnsyncByteArrayInputStream) ReferenceType(org.apache.xml.security.binding.xmlenc.ReferenceType) XMLSecurityException(org.apache.xml.security.exceptions.XMLSecurityException) XMLSecEvent(org.apache.xml.security.stax.ext.stax.XMLSecEvent) XMLSecStartElement(org.apache.xml.security.stax.ext.stax.XMLSecStartElement) InboundSecurityToken(org.apache.xml.security.stax.securityToken.InboundSecurityToken) Key(java.security.Key)

Example 2 with XMLSecEvent

use of org.apache.xml.security.stax.ext.stax.XMLSecEvent in project santuario-java by apache.

the class AbstractSignatureInputHandler method verifySignedInfo.

protected InboundSecurityToken verifySignedInfo(InputProcessorChain inputProcessorChain, XMLSecurityProperties securityProperties, SignatureType signatureType, Deque<XMLSecEvent> eventDeque, int index) throws XMLSecurityException {
    Iterator<XMLSecEvent> iterator;
    String c14NMethod = signatureType.getSignedInfo().getCanonicalizationMethod().getAlgorithm();
    if (XMLSecurityConstants.NS_C14N_OMIT_COMMENTS.equals(c14NMethod) || XMLSecurityConstants.NS_C14N_WITH_COMMENTS.equals(c14NMethod) || XMLSecurityConstants.NS_C14N_EXCL_OMIT_COMMENTS.equals(c14NMethod) || XMLSecurityConstants.NS_C14N_EXCL_WITH_COMMENTS.equals(c14NMethod) || XMLSecurityConstants.NS_C14N11_OMIT_COMMENTS.equals(c14NMethod) || XMLSecurityConstants.NS_C14N11_WITH_COMMENTS.equals(c14NMethod)) {
        iterator = eventDeque.descendingIterator();
        // forward to <Signature> Element
        int i = 0;
        while (i < index) {
            iterator.next();
            i++;
        }
    } else {
        iterator = reparseSignedInfo(inputProcessorChain, securityProperties, signatureType, eventDeque, index).descendingIterator();
        index = 0;
    }
    SignatureVerifier signatureVerifier = newSignatureVerifier(inputProcessorChain, securityProperties, signatureType);
    try {
        loop: while (iterator.hasNext()) {
            XMLSecEvent xmlSecEvent = iterator.next();
            switch(xmlSecEvent.getEventType()) {
                case XMLStreamConstants.START_ELEMENT:
                    if (xmlSecEvent.asStartElement().getName().equals(XMLSecurityConstants.TAG_dsig_SignedInfo)) {
                        signatureVerifier.processEvent(xmlSecEvent);
                        break loop;
                    }
                    break;
            }
        }
        loop: while (iterator.hasNext()) {
            XMLSecEvent xmlSecEvent = iterator.next();
            signatureVerifier.processEvent(xmlSecEvent);
            switch(xmlSecEvent.getEventType()) {
                case XMLStreamConstants.END_ELEMENT:
                    if (xmlSecEvent.asEndElement().getName().equals(XMLSecurityConstants.TAG_dsig_SignedInfo)) {
                        break loop;
                    }
                    break;
            }
        }
    } catch (XMLStreamException e) {
        throw new XMLSecurityException(e);
    }
    signatureVerifier.doFinal();
    return signatureVerifier.getInboundSecurityToken();
}
Also used : XMLStreamException(javax.xml.stream.XMLStreamException) XMLSecurityException(org.apache.xml.security.exceptions.XMLSecurityException) XMLSecEvent(org.apache.xml.security.stax.ext.stax.XMLSecEvent)

Example 3 with XMLSecEvent

use of org.apache.xml.security.stax.ext.stax.XMLSecEvent in project santuario-java by apache.

the class XMLEventReaderInputProcessor method processNextEventInternal.

private XMLSecEvent processNextEventInternal() throws XMLStreamException {
    XMLSecEvent xmlSecEvent = XMLSecEventFactory.allocate(xmlStreamReader, parentXmlSecStartElement);
    switch(xmlSecEvent.getEventType()) {
        case XMLStreamConstants.START_ELEMENT:
            currentXMLStructureDepth++;
            if (currentXMLStructureDepth > maximumAllowedXMLStructureDepth) {
                XMLSecurityException xmlSecurityException = new XMLSecurityException("secureProcessing.MaximumAllowedXMLStructureDepth", new Object[] { maximumAllowedXMLStructureDepth });
                throw new XMLStreamException(xmlSecurityException);
            }
            parentXmlSecStartElement = (XMLSecStartElement) xmlSecEvent;
            break;
        case XMLStreamConstants.END_ELEMENT:
            currentXMLStructureDepth--;
            if (parentXmlSecStartElement != null) {
                parentXmlSecStartElement = parentXmlSecStartElement.getParentXMLSecStartElement();
            }
            break;
    }
    if (xmlStreamReader.hasNext()) {
        xmlStreamReader.next();
    } else {
        if (EOF) {
            throw new NoSuchElementException();
        }
        EOF = true;
    }
    return xmlSecEvent;
}
Also used : XMLStreamException(javax.xml.stream.XMLStreamException) XMLSecurityException(org.apache.xml.security.exceptions.XMLSecurityException) NoSuchElementException(java.util.NoSuchElementException) XMLSecEvent(org.apache.xml.security.stax.ext.stax.XMLSecEvent)

Example 4 with XMLSecEvent

use of org.apache.xml.security.stax.ext.stax.XMLSecEvent in project santuario-java by apache.

the class XMLSignatureEndingOutputProcessor method flushBufferAndCallbackAfterHeader.

@Override
protected void flushBufferAndCallbackAfterHeader(OutputProcessorChain outputProcessorChain, Deque<XMLSecEvent> xmlSecEventDeque) throws XMLStreamException, XMLSecurityException {
    // forward to the root element and output it
    XMLSecEvent xmlSecEvent = xmlSecEventDeque.pop();
    while (!xmlSecEvent.isStartElement()) {
        outputProcessorChain.reset();
        outputProcessorChain.processEvent(xmlSecEvent);
        xmlSecEvent = xmlSecEventDeque.pop();
    }
    outputProcessorChain.reset();
    outputProcessorChain.processEvent(xmlSecEvent);
    // search the specified position
    int depth = 0;
    QName signaturePositionQName = getSecurityProperties().getSignaturePositionQName();
    boolean start = getSecurityProperties().isSignaturePositionStart();
    if (signaturePositionQName != null) {
        while (!xmlSecEventDeque.isEmpty() && !(start && xmlSecEvent.isStartElement() && xmlSecEvent.asStartElement().getName().equals(signaturePositionQName) || !start && xmlSecEvent.isEndElement() && xmlSecEvent.asEndElement().getName().equals(signaturePositionQName))) {
            xmlSecEvent = xmlSecEventDeque.pop();
            if (xmlSecEvent.isStartElement()) {
                depth++;
            } else if (xmlSecEvent.isEndElement()) {
                depth--;
                if (depth < 0) {
                    // root-end-element reached
                    xmlSecEventDeque.push(xmlSecEvent);
                    break;
                }
            }
            outputProcessorChain.reset();
            outputProcessorChain.processEvent(xmlSecEvent);
        }
    } else {
        // @see SANTUARIO-405
        // Enhances SANTUARIO-324
        // Output the signature at a specific position.
        // By default, this is just after the root element
        int signaturePosition = getSecurityProperties().getSignaturePosition();
        if (signaturePosition < 0) {
            signaturePosition = 0;
        }
        int position = 0;
        while (position != signaturePosition) {
            xmlSecEvent = xmlSecEventDeque.pop();
            if (xmlSecEvent.isStartElement()) {
                depth++;
            } else if (xmlSecEvent.isEndElement()) {
                depth--;
                if (depth == 0) {
                    position++;
                } else if (depth < 0) {
                    // root-end-element reached
                    xmlSecEventDeque.push(xmlSecEvent);
                    break;
                }
            }
            outputProcessorChain.reset();
            outputProcessorChain.processEvent(xmlSecEvent);
        }
    }
    // ...then call super to append the signature and flush the rest
    super.flushBufferAndCallbackAfterHeader(outputProcessorChain, xmlSecEventDeque);
}
Also used : QName(javax.xml.namespace.QName) XMLSecEvent(org.apache.xml.security.stax.ext.stax.XMLSecEvent)

Example 5 with XMLSecEvent

use of org.apache.xml.security.stax.ext.stax.XMLSecEvent in project santuario-java by apache.

the class TransformBase64Decode method transform.

@Override
public void transform(XMLSecEvent xmlSecEvent) throws XMLStreamException {
    int eventType = xmlSecEvent.getEventType();
    switch(eventType) {
        case XMLStreamConstants.CHARACTERS:
            if (getOutputStream() != null) {
                // encoding shouldn't matter here, because the data is Base64 encoded and is therefore in the ASCII range.
                try {
                    getOutputStream().write(xmlSecEvent.asCharacters().getData().getBytes());
                } catch (IOException e) {
                    throw new XMLStreamException(e);
                }
            } else {
                // we have a child transformer
                if (childOutputMethod == null) {
                    final XMLSecurityConstants.TransformMethod preferredChildTransformMethod = getTransformer().getPreferredTransformMethod(XMLSecurityConstants.TransformMethod.XMLSecEvent);
                    switch(preferredChildTransformMethod) {
                        case XMLSecEvent:
                            {
                                childOutputMethod = new ChildOutputMethod() {

                                    private UnsyncByteArrayOutputStream byteArrayOutputStream;

                                    private Base64OutputStream base64OutputStream;

                                    @Override
                                    public void transform(Object object) throws XMLStreamException {
                                        if (base64OutputStream == null) {
                                            byteArrayOutputStream = new UnsyncByteArrayOutputStream();
                                            base64OutputStream = new Base64OutputStream(byteArrayOutputStream, false);
                                        }
                                        try {
                                            base64OutputStream.write((byte[]) object);
                                        } catch (IOException e) {
                                            throw new XMLStreamException(e);
                                        }
                                    }

                                    @Override
                                    public void doFinal() throws XMLStreamException {
                                        try {
                                            base64OutputStream.close();
                                        } catch (IOException e) {
                                            throw new XMLStreamException(e);
                                        }
                                        try (InputStream is = new UnsyncByteArrayInputStream(byteArrayOutputStream.toByteArray())) {
                                            XMLEventReaderInputProcessor xmlEventReaderInputProcessor = new XMLEventReaderInputProcessor(null, getXmlInputFactory().createXMLStreamReader(is));
                                            XMLSecEvent xmlSecEvent;
                                            do {
                                                xmlSecEvent = xmlEventReaderInputProcessor.processNextEvent(null);
                                                getTransformer().transform(xmlSecEvent);
                                            } while (xmlSecEvent.getEventType() != XMLStreamConstants.END_DOCUMENT);
                                        } catch (XMLSecurityException | IOException e) {
                                            throw new XMLStreamException(e);
                                        }
                                        getTransformer().doFinal();
                                    }
                                };
                                break;
                            }
                        case InputStream:
                            {
                                childOutputMethod = new ChildOutputMethod() {

                                    private UnsyncByteArrayOutputStream byteArrayOutputStream;

                                    private Base64OutputStream base64OutputStream;

                                    @Override
                                    public void transform(Object object) throws XMLStreamException {
                                        if (base64OutputStream == null) {
                                            byteArrayOutputStream = new UnsyncByteArrayOutputStream();
                                            base64OutputStream = new Base64OutputStream(byteArrayOutputStream, false);
                                        }
                                        try {
                                            base64OutputStream.write((byte[]) object);
                                        } catch (IOException e) {
                                            throw new XMLStreamException(e);
                                        }
                                    }

                                    @Override
                                    public void doFinal() throws XMLStreamException {
                                        try {
                                            base64OutputStream.close();
                                        } catch (IOException e) {
                                            throw new XMLStreamException(e);
                                        }
                                        try (InputStream is = new UnsyncByteArrayInputStream(byteArrayOutputStream.toByteArray())) {
                                            getTransformer().transform(is);
                                            getTransformer().doFinal();
                                        } catch (IOException ex) {
                                            throw new XMLStreamException(ex);
                                        }
                                    }
                                };
                                break;
                            }
                    }
                }
                childOutputMethod.transform(xmlSecEvent.asCharacters().getData().getBytes());
            }
            break;
    }
}
Also used : XMLSecurityConstants(org.apache.xml.security.stax.ext.XMLSecurityConstants) UnsyncByteArrayOutputStream(org.apache.xml.security.utils.UnsyncByteArrayOutputStream) UnsyncByteArrayInputStream(org.apache.xml.security.utils.UnsyncByteArrayInputStream) Base64InputStream(org.apache.commons.codec.binary.Base64InputStream) XMLEventReaderInputProcessor(org.apache.xml.security.stax.impl.processor.input.XMLEventReaderInputProcessor) Base64OutputStream(org.apache.commons.codec.binary.Base64OutputStream) XMLSecurityException(org.apache.xml.security.exceptions.XMLSecurityException) XMLSecEvent(org.apache.xml.security.stax.ext.stax.XMLSecEvent) XMLStreamException(javax.xml.stream.XMLStreamException) UnsyncByteArrayInputStream(org.apache.xml.security.utils.UnsyncByteArrayInputStream)

Aggregations

XMLSecEvent (org.apache.xml.security.stax.ext.stax.XMLSecEvent)46 ByteArrayOutputStream (java.io.ByteArrayOutputStream)25 Test (org.junit.Test)25 XMLEventReader (javax.xml.stream.XMLEventReader)22 XMLSecurityConstants (org.apache.xml.security.stax.ext.XMLSecurityConstants)16 InputStream (java.io.InputStream)15 OutputStream (java.io.OutputStream)14 Map (java.util.Map)14 QName (javax.xml.namespace.QName)14 Transformer (org.apache.xml.security.stax.ext.Transformer)14 IOException (java.io.IOException)10 XMLSecurityException (org.apache.xml.security.exceptions.XMLSecurityException)9 XMLStreamException (javax.xml.stream.XMLStreamException)6 Canonicalizer20010315_OmitCommentsTransformer (org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_OmitCommentsTransformer)6 ArrayList (java.util.ArrayList)5 TransformBase64Decode (org.apache.xml.security.stax.impl.transformer.TransformBase64Decode)5 TransformIdentity (org.apache.xml.security.stax.impl.transformer.TransformIdentity)5 XMLStreamReader (javax.xml.stream.XMLStreamReader)4 Canonicalizer20010315_WithCommentsTransformer (org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_WithCommentsTransformer)4 UnixInputStream (org.apache.xml.security.test.stax.utils.UnixInputStream)4