1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 }