View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.impl.processor.output;
20  
21  import java.util.ArrayList;
22  import java.util.Deque;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.xml.stream.XMLStreamConstants;
27  import javax.xml.stream.XMLStreamException;
28  
29  import org.apache.wss4j.stax.ext.WSSConstants;
30  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
31  import org.apache.wss4j.stax.impl.SecurityHeaderOrder;
32  import org.apache.wss4j.stax.utils.WSSUtils;
33  import org.apache.xml.security.exceptions.XMLSecurityException;
34  import org.apache.xml.security.stax.ext.OutputProcessorChain;
35  import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
36  import org.apache.xml.security.stax.impl.EncryptionPartDef;
37  import org.apache.xml.security.stax.impl.processor.output.AbstractEncryptEndingOutputProcessor;
38  
39  /**
40   * Processor buffers encrypted XMLEvents and forwards them when final is called
41   */
42  public class EncryptEndingOutputProcessor extends AbstractEncryptEndingOutputProcessor {
43  
44      public EncryptEndingOutputProcessor() throws XMLSecurityException {
45          super();
46          this.addAfterProcessor(EncryptOutputProcessor.class);
47          this.addAfterProcessor(UsernameTokenOutputProcessor.class);
48      }
49  
50      @Override
51      public void processHeaderEvent(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
52          OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
53          if (attachmentCount(outputProcessorChain) > 0) {
54              WSSUtils.createEncryptedDataStructureForAttachments(this, subOutputProcessorChain);
55          }
56      }
57  
58      @Override
59      public void flushBufferAndCallbackAfterHeader(OutputProcessorChain outputProcessorChain,
60                                                     Deque<XMLSecEvent> xmlSecEventDeque)
61              throws XMLStreamException, XMLSecurityException {
62  
63          final String actor = ((WSSSecurityProperties) getSecurityProperties()).getActor();
64  
65          //loop until we reach our security header
66          loop:
67          while (!xmlSecEventDeque.isEmpty()) {
68              XMLSecEvent xmlSecEvent = xmlSecEventDeque.pop();
69              if (XMLStreamConstants.START_ELEMENT == xmlSecEvent.getEventType()
70                      && WSSUtils.isSecurityHeaderElement(xmlSecEvent, actor)) {
71                  int attachmentCount = attachmentCount(outputProcessorChain);
72                  for (int i = 0; i < attachmentCount; i++) {
73                      OutputProcessorUtils.updateSecurityHeaderOrder(
74                              outputProcessorChain, WSSConstants.TAG_xenc_EncryptedData, getAction(), true);
75                  }
76                  List<SecurityHeaderOrder> securityHeaderOrderList =
77                          outputProcessorChain.getSecurityContext().getAsList(SecurityHeaderOrder.class);
78                  List<SecurityHeaderOrder> tmpList = null;
79                  if (securityHeaderOrderList != null) {
80                      tmpList = new ArrayList<>(securityHeaderOrderList);
81                      securityHeaderOrderList.clear();
82                  }
83  
84                  outputProcessorChain.reset();
85                  outputProcessorChain.processEvent(xmlSecEvent);
86  
87                  if (securityHeaderOrderList != null) {
88                      securityHeaderOrderList.addAll(tmpList);
89                  }
90                  break loop;
91              }
92              outputProcessorChain.reset();
93              outputProcessorChain.processEvent(xmlSecEvent);
94          }
95          super.flushBufferAndCallbackAfterHeader(outputProcessorChain, xmlSecEventDeque);
96      }
97  
98      private int attachmentCount(OutputProcessorChain outputProcessorChain) {
99          List<EncryptionPartDef> encryptionPartDefs =
100                 outputProcessorChain.getSecurityContext().getAsList(EncryptionPartDef.class);
101         if (encryptionPartDefs == null) {
102             return 0;
103         }
104 
105         int count = 0;
106         Iterator<EncryptionPartDef> encryptionPartDefIterator = encryptionPartDefs.iterator();
107         while (encryptionPartDefIterator.hasNext()) {
108             EncryptionPartDef encryptionPartDef = encryptionPartDefIterator.next();
109 
110             if (encryptionPartDef.getCipherReferenceId() != null) {
111                 count++;
112             }
113         }
114         return count;
115     }
116 }