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.security.Key;
22  import java.security.PublicKey;
23  import java.security.cert.X509Certificate;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import javax.xml.namespace.QName;
28  import javax.xml.stream.XMLStreamException;
29  
30  import org.apache.wss4j.common.ext.WSSecurityException;
31  import org.apache.wss4j.stax.ext.WSSConstants;
32  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
33  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
34  import org.apache.wss4j.stax.utils.WSSUtils;
35  import org.apache.xml.security.exceptions.XMLSecurityException;
36  import org.apache.xml.security.stax.ext.AbstractOutputProcessor;
37  import org.apache.xml.security.stax.ext.OutputProcessorChain;
38  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
39  import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
40  import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
41  import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
42  import org.apache.xml.security.stax.impl.util.IDGenerator;
43  import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
44  import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
45  
46  public class SecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
47  
48      public SecurityContextTokenOutputProcessor() throws XMLSecurityException {
49          super();
50      }
51  
52      @Override
53      public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
54              throws XMLStreamException, XMLSecurityException {
55          try {
56              String tokenId = outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN);
57              if (tokenId == null) {
58                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
59              }
60              SecurityTokenProvider<OutboundSecurityToken> wrappingSecurityTokenProvider =
61                  outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
62              if (wrappingSecurityTokenProvider == null) {
63                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
64              }
65              final OutboundSecurityToken wrappingSecurityToken = wrappingSecurityTokenProvider.getSecurityToken();
66              if (wrappingSecurityToken == null) {
67                  throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE);
68              }
69  
70              final String wsuId = IDGenerator.generateID(null);
71              final String identifier = IDGenerator.generateID(null);
72  
73              final GenericOutboundSecurityToken securityContextSecurityToken =
74                  new GenericOutboundSecurityToken(wsuId, WSSecurityTokenConstants.SECURITY_CONTEXT_TOKEN) {
75  
76                  @Override
77                  public Key getSecretKey(String algorithmURI) throws XMLSecurityException {
78                      return wrappingSecurityToken.getSecretKey(algorithmURI);
79                  }
80  
81                  @Override
82                  public PublicKey getPublicKey() throws XMLSecurityException {
83                      return wrappingSecurityToken.getPublicKey();
84                  }
85  
86                  @Override
87                  public X509Certificate[] getX509Certificates() throws XMLSecurityException {
88                      return wrappingSecurityToken.getX509Certificates();
89                  }
90              };
91              wrappingSecurityToken.addWrappedToken(securityContextSecurityToken);
92  
93              SecurityTokenProvider<OutboundSecurityToken> securityContextSecurityTokenProvider =
94                      new SecurityTokenProvider<OutboundSecurityToken>() {
95  
96                  @Override
97                  public OutboundSecurityToken getSecurityToken() throws WSSecurityException {
98                      return securityContextSecurityToken;
99                  }
100 
101                 @Override
102                 public String getId() {
103                     return wsuId;
104                 }
105             };
106 
107             FinalSecurityContextTokenOutputProcessor finalSecurityContextTokenOutputProcessor =
108                     new FinalSecurityContextTokenOutputProcessor(securityContextSecurityToken, identifier,
109                                                                  ((WSSSecurityProperties)getSecurityProperties()).isUse200512Namespace());
110             finalSecurityContextTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
111             finalSecurityContextTokenOutputProcessor.setAction(getAction(), getActionOrder());
112             XMLSecurityConstants.Action action = getAction();
113             if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
114                 outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
115                 if (wrappingSecurityToken.getProcessor() != null) {
116                     finalSecurityContextTokenOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor().getClass());
117                 } else {
118                     finalSecurityContextTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class);
119                 }
120             } else if (WSSConstants.ENCRYPTION_WITH_DERIVED_KEY.equals(action)) {
121                 outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
122                 if (wrappingSecurityToken.getProcessor() != null) {
123                     finalSecurityContextTokenOutputProcessor.addBeforeProcessor(wrappingSecurityToken.getProcessor().getClass());
124                 } else {
125                     finalSecurityContextTokenOutputProcessor.addAfterProcessor(ReferenceListOutputProcessor.class);
126                     finalSecurityContextTokenOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class);
127                 }
128             }
129 
130             finalSecurityContextTokenOutputProcessor.init(outputProcessorChain);
131             outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(wsuId, securityContextSecurityTokenProvider);
132             securityContextSecurityToken.setProcessor(finalSecurityContextTokenOutputProcessor);
133 
134         } finally {
135             outputProcessorChain.removeProcessor(this);
136         }
137         outputProcessorChain.processEvent(xmlSecEvent);
138     }
139 
140     static class FinalSecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
141 
142         private final OutboundSecurityToken securityToken;
143         private final String identifier;
144         private final boolean use200512Namespace;
145 
146         FinalSecurityContextTokenOutputProcessor(OutboundSecurityToken securityToken, String identifier, boolean use200512Namespace)
147             throws XMLSecurityException {
148             super();
149             this.securityToken = securityToken;
150             this.identifier = identifier;
151             this.use200512Namespace = use200512Namespace;
152         }
153 
154         @Override
155         public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain)
156                 throws XMLStreamException, XMLSecurityException {
157 
158             outputProcessorChain.processEvent(xmlSecEvent);
159 
160             if (WSSUtils.isSecurityHeaderElement(xmlSecEvent, ((WSSSecurityProperties) getSecurityProperties()).getActor())) {
161 
162                 final QName headerElementName = getHeaderElementName();
163                 OutputProcessorUtils.updateSecurityHeaderOrder(outputProcessorChain, headerElementName, getAction(), false);
164 
165                 OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
166 
167                 List<XMLSecAttribute> attributes = new ArrayList<>(1);
168                 attributes.add(createAttribute(WSSConstants.ATT_WSU_ID, securityToken.getId()));
169                 QName identifierName = getIdentifierName();
170                 createStartElementAndOutputAsEvent(subOutputProcessorChain, headerElementName, true, attributes);
171                 createStartElementAndOutputAsEvent(subOutputProcessorChain, identifierName, false, null);
172                 createCharactersAndOutputAsEvent(subOutputProcessorChain, identifier);
173                 createEndElementAndOutputAsEvent(subOutputProcessorChain, identifierName);
174                 createEndElementAndOutputAsEvent(subOutputProcessorChain, headerElementName);
175 
176                 outputProcessorChain.removeProcessor(this);
177             }
178         }
179 
180         private QName getHeaderElementName() {
181             if (use200512Namespace) {
182                 return WSSConstants.TAG_WSC0512_SCT;
183             }
184             return WSSConstants.TAG_WSC0502_SCT;
185         }
186 
187         private QName getIdentifierName() {
188             if (use200512Namespace) {
189                 return WSSConstants.TAG_WSC0512_IDENTIFIER;
190             }
191             return WSSConstants.TAG_WSC0502_IDENTIFIER;
192         }
193     }
194 }