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.List;
23  
24  import javax.xml.namespace.QName;
25  import javax.xml.stream.XMLStreamException;
26  
27  import org.apache.wss4j.stax.ext.WSSConstants;
28  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
29  import org.apache.wss4j.stax.impl.securityToken.KerberosClientSecurityToken;
30  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
31  import org.apache.wss4j.stax.utils.WSSUtils;
32  import org.apache.xml.security.exceptions.XMLSecurityException;
33  import org.apache.xml.security.stax.ext.AbstractOutputProcessor;
34  import org.apache.xml.security.stax.ext.OutputProcessorChain;
35  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
36  import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
37  import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
38  import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
39  import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
40  import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
41  import org.apache.xml.security.utils.XMLUtils;
42  
43  public class BinarySecurityTokenOutputProcessor extends AbstractOutputProcessor {
44  
45      public BinarySecurityTokenOutputProcessor() throws XMLSecurityException {
46          super();
47          addBeforeProcessor(WSSSignatureOutputProcessor.class);
48      }
49  
50      @Override
51      public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
52          throws XMLStreamException, XMLSecurityException {
53          try {
54              GenericOutboundSecurityToken securityToken = null;
55  
56              XMLSecurityConstants.Action action = getAction();
57              String tokenId = null;
58              if (WSSConstants.SIGNATURE.equals(action)
59                      || WSSConstants.SAML_TOKEN_SIGNED.equals(action)) {
60                  tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE);
61              } else if (WSSConstants.ENCRYPTION.equals(action)) {
62                  tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY);
63              } else if (WSSConstants.ENCRYPTION_WITH_KERBEROS_TOKEN.equals(getAction())
64                  || WSSConstants.SIGNATURE_WITH_KERBEROS_TOKEN.equals(getAction())
65                  || WSSConstants.KERBEROS_TOKEN.equals(getAction())) {
66                  tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_KERBEROS);
67              }
68  
69              SecurityTokenProvider<OutboundSecurityToken> tokenProvider = null;
70              if (tokenId != null) {
71                  tokenProvider =
72                      outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
73                  if (tokenProvider != null) {
74                      securityToken = (GenericOutboundSecurityToken)tokenProvider.getSecurityToken();
75                  }
76              }
77  
78              boolean includeToken = false;
79              WSSecurityTokenConstants.KeyIdentifier keyIdentifier = null;
80              if ((WSSConstants.SIGNATURE.equals(action) || WSSConstants.SAML_TOKEN_SIGNED.equals(action))
81                  && !getSecurityProperties().getSignatureKeyIdentifiers().isEmpty()) {
82                  includeToken = ((WSSSecurityProperties) getSecurityProperties()).isIncludeSignatureToken();
83                  keyIdentifier = getSecurityProperties().getSignatureKeyIdentifiers().get(0);
84              } else if (WSSConstants.ENCRYPTION.equals(action)) {
85                  includeToken = ((WSSSecurityProperties) getSecurityProperties()).isIncludeEncryptionToken();
86                  keyIdentifier = getSecurityProperties().getEncryptionKeyIdentifier();
87              }
88  
89              if (securityToken != null) {
90                  if (WSSConstants.SIGNATURE.equals(action)
91                      && (includeToken || WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier))
92                      && (securityToken.getTokenType() == null
93                      || WSSecurityTokenConstants.X509V3Token.equals(securityToken.getTokenType()))) {
94                      FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor =
95                          new FinalBinarySecurityTokenOutputProcessor(securityToken);
96                      finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
97                      finalBinarySecurityTokenOutputProcessor.setAction(getAction(), getActionOrder());
98                      finalBinarySecurityTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
99                      finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
100                     securityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
101                 } else if (WSSConstants.SAML_TOKEN_SIGNED.equals(action) && includeToken
102                     && (securityToken.getTokenType() == null
103                         || WSSecurityTokenConstants.X509V3Token.equals(securityToken.getTokenType()))) {
104                     FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor =
105                         new FinalBinarySecurityTokenOutputProcessor(securityToken);
106                     finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
107                     finalBinarySecurityTokenOutputProcessor.setAction(getAction(), getActionOrder());
108                     finalBinarySecurityTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
109                     finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
110                     securityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
111                 } else if (WSSConstants.ENCRYPTION.equals(action)
112                     && (includeToken || WSSecurityTokenConstants.KEYIDENTIFIER_SECURITY_TOKEN_DIRECT_REFERENCE.equals(keyIdentifier))
113                     && (securityToken.getTokenType() == null
114                         || WSSecurityTokenConstants.X509V3Token.equals(securityToken.getTokenType()))) {
115                     FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor =
116                         new FinalBinarySecurityTokenOutputProcessor(securityToken);
117                     finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
118                     finalBinarySecurityTokenOutputProcessor.setAction(getAction(), getActionOrder());
119                     finalBinarySecurityTokenOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
120                     finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
121                     securityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
122                 } else if (WSSConstants.ENCRYPTION_WITH_KERBEROS_TOKEN.equals(getAction())
123                     || WSSConstants.SIGNATURE_WITH_KERBEROS_TOKEN.equals(getAction())
124                     || WSSConstants.KERBEROS_TOKEN.equals(getAction())) {
125                     FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor =
126                         new FinalBinarySecurityTokenOutputProcessor(securityToken);
127                     finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
128                     finalBinarySecurityTokenOutputProcessor.setAction(getAction(), getActionOrder());
129                     finalBinarySecurityTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
130                     finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
131                     securityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
132                 }
133             }
134         } finally {
135             outputProcessorChain.removeProcessor(this);
136         }
137         outputProcessorChain.processEvent(xmlSecEvent);
138     }
139 
140     static class FinalBinarySecurityTokenOutputProcessor extends AbstractOutputProcessor {
141 
142         private final OutboundSecurityToken securityToken;
143 
144         FinalBinarySecurityTokenOutputProcessor(OutboundSecurityToken securityToken) throws XMLSecurityException {
145             super();
146             this.addAfterProcessor(BinarySecurityTokenOutputProcessor.class);
147             this.securityToken = securityToken;
148         }
149 
150         @Override
151         public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
152                 throws XMLStreamException, XMLSecurityException {
153 
154             outputProcessorChain.processEvent(xmlSecEvent);
155 
156             if (WSSUtils.isSecurityHeaderElement(xmlSecEvent, ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
157 
158                 final QName headerElementName = WSSConstants.TAG_WSSE_BINARY_SECURITY_TOKEN;
159 
160                 if (WSSConstants.ENCRYPTION_WITH_KERBEROS_TOKEN.equals(getAction())
161                     || WSSConstants.SIGNATURE_WITH_KERBEROS_TOKEN.equals(getAction())
162                     || WSSConstants.KERBEROS_TOKEN.equals(getAction())) {
163                     OutputProcessorUtils.updateSecurityHeaderOrder(
164                         outputProcessorChain, headerElementName, getAction(), false);
165                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
166 
167                     List<XMLSecAttribute> attributes = new ArrayList<>(3);
168                     attributes.add(createAttribute(WSSConstants.ATT_NULL_ENCODING_TYPE, WSSConstants.SOAPMESSAGE_NS10_BASE64_ENCODING));
169                     attributes.add(createAttribute(WSSConstants.ATT_NULL_VALUE_TYPE, WSSConstants.NS_GSS_KERBEROS5_AP_REQ));
170                     attributes.add(createAttribute(WSSConstants.ATT_WSU_ID, securityToken.getId()));
171                     createStartElementAndOutputAsEvent(subOutputProcessorChain, headerElementName, false, attributes);
172                     createCharactersAndOutputAsEvent(subOutputProcessorChain,
173                             XMLUtils.encodeToString(
174                                 ((KerberosClientSecurityToken)securityToken).getTicket())
175                     );
176                     createEndElementAndOutputAsEvent(subOutputProcessorChain, headerElementName);
177                     if (WSSConstants.ENCRYPTION_WITH_KERBEROS_TOKEN.equals(getAction())) {
178                         OutputProcessorUtils.updateSecurityHeaderOrder(outputProcessorChain, WSSConstants.TAG_xenc_ReferenceList,
179                                                                        getAction(), false);
180                         WSSUtils.createReferenceListStructureForEncryption(this, subOutputProcessorChain);
181                     }
182                 } else if (securityToken.getX509Certificates() != null
183                     && securityToken.getX509Certificates().length > 0) {
184                     OutputProcessorUtils.updateSecurityHeaderOrder(
185                         outputProcessorChain, headerElementName, getAction(), false);
186                     OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
187 
188                     boolean useSingleCertificate = getSecurityProperties().isUseSingleCert();
189                     WSSUtils.createBinarySecurityTokenStructure(
190                             this, subOutputProcessorChain, securityToken.getId(),
191                             securityToken.getX509Certificates(), useSingleCertificate);
192                 }
193 
194                 outputProcessorChain.removeProcessor(this);
195             }
196         }
197     }
198 }