1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.policy.stax.assertionStates;
20
21 import org.apache.neethi.Assertion;
22 import org.apache.wss4j.policy.AssertionState;
23 import org.apache.wss4j.policy.SPConstants;
24 import org.apache.wss4j.common.WSSPolicyException;
25 import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
26 import org.apache.wss4j.policy.stax.Assertable;
27 import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
28 import org.apache.wss4j.policy.stax.PolicyAsserter;
29 import org.apache.wss4j.stax.ext.WSSConstants;
30 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
31 import org.apache.wss4j.stax.utils.WSSUtils;
32 import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
33 import org.apache.xml.security.exceptions.XMLSecurityException;
34 import org.apache.xml.security.stax.securityEvent.SecurityEvent;
35 import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
36 import org.apache.xml.security.stax.securityEvent.SignedElementSecurityEvent;
37 import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
38 import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
39 import org.apache.xml.security.stax.securityToken.SecurityToken;
40
41 import javax.xml.namespace.QName;
42
43 import java.util.ArrayList;
44 import java.util.LinkedList;
45 import java.util.List;
46
47
48
49
50 public class TokenProtectionAssertionState extends AssertionState implements Assertable {
51
52 private final List<SignedElementSecurityEvent> signedElementEvents = new ArrayList<>();
53 private final List<TokenSecurityEvent<? extends SecurityToken>> tokenSecurityEvents = new ArrayList<>();
54 private PolicyAsserter policyAsserter;
55 private final boolean soap12;
56
57 public TokenProtectionAssertionState(Assertion assertion,
58 PolicyAsserter policyAsserter,
59 boolean initialAssertionState,
60 boolean soap12) {
61 super(assertion, initialAssertionState);
62
63 this.policyAsserter = policyAsserter;
64 if (this.policyAsserter == null) {
65 this.policyAsserter = new DummyPolicyAsserter();
66 }
67
68 if (initialAssertionState) {
69 String namespace = getAssertion().getName().getNamespaceURI();
70 policyAsserter.assertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS));
71 }
72
73 this.soap12 = soap12;
74 }
75
76 @Override
77 public SecurityEventConstants.Event[] getSecurityEventType() {
78 return new SecurityEventConstants.Event[]{
79 SecurityEventConstants.SignedElement,
80 WSSecurityEventConstants.EncryptedKeyToken,
81 WSSecurityEventConstants.ISSUED_TOKEN,
82 WSSecurityEventConstants.KERBEROS_TOKEN,
83 SecurityEventConstants.KeyValueToken,
84 WSSecurityEventConstants.REL_TOKEN,
85 WSSecurityEventConstants.SAML_TOKEN,
86 WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
87 WSSecurityEventConstants.USERNAME_TOKEN,
88 SecurityEventConstants.X509Token,
89 WSSecurityEventConstants.OPERATION,
90 };
91 }
92
93 @Override
94 public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException, XMLSecurityException {
95
96 AbstractSymmetricAsymmetricBinding abstractSymmetricAsymmetricBinding = (AbstractSymmetricAsymmetricBinding) getAssertion();
97 boolean protectTokens = abstractSymmetricAsymmetricBinding.isProtectTokens();
98 String namespace = getAssertion().getName().getNamespaceURI();
99
100 if (securityEvent instanceof SignedElementSecurityEvent) {
101 SignedElementSecurityEvent signedElementSecurityEvent = (SignedElementSecurityEvent) securityEvent;
102 if (signedElementSecurityEvent.isSigned()) {
103 signedElementEvents.add(signedElementSecurityEvent);
104 }
105 } else if (securityEvent instanceof TokenSecurityEvent) {
106 @SuppressWarnings("unchecked")
107 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent
108 = (TokenSecurityEvent<? extends SecurityToken>) securityEvent;
109 tokenSecurityEvents.add(tokenSecurityEvent);
110 } else {
111 for (int i = 0; i < tokenSecurityEvents.size(); i++) {
112 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
113
114 SecurityToken securityToken = getEffectiveSignatureToken(tokenSecurityEvent.getSecurityToken());
115
116
117 if (((InboundSecurityToken)securityToken).isIncludedInMessage() && isSignatureToken(securityToken)) {
118
119 boolean signsItsSignatureToken = signsItsSignatureToken(securityToken);
120 if (protectTokens && !signsItsSignatureToken) {
121 setAsserted(false);
122 setErrorMessage("Token " + WSSUtils.pathAsString(((InboundSecurityToken)securityToken).getElementPath())
123 + " must be signed by its signature.");
124 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS),
125 getErrorMessage());
126 return false;
127 } else if (!protectTokens && signsItsSignatureToken) {
128 setAsserted(false);
129 setErrorMessage("Token " + WSSUtils.pathAsString(((InboundSecurityToken)securityToken).getElementPath())
130 + " must not be signed by its signature.");
131 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS),
132 getErrorMessage());
133 return false;
134 }
135 }
136
137 if (isEndorsingToken(securityToken) && !signsMainSignature(securityToken)) {
138
139 setAsserted(false);
140 setErrorMessage("Token " + WSSUtils.pathAsString(((InboundSecurityToken)securityToken).getElementPath())
141 + " must sign the main signature.");
142 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS),
143 getErrorMessage());
144 return false;
145 }
146
147 if (isMainSignatureToken(securityToken)
148 && !signsSignedSupportingTokens(securityToken)) {
149 setAsserted(false);
150 setErrorMessage("Main signature must sign the Signed*Supporting-Tokens.");
151 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS),
152 getErrorMessage());
153 return false;
154 }
155 }
156 }
157
158 policyAsserter.assertPolicy(new QName(namespace, SPConstants.PROTECT_TOKENS));
159 return true;
160 }
161
162 private boolean isSignatureToken(SecurityToken securityToken) {
163 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = securityToken.getTokenUsages();
164 for (int i = 0; i < tokenUsages.size(); i++) {
165 WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsages.get(i);
166 if (WSSecurityTokenConstants.TokenUsage_Signature.equals(tokenUsage)
167 || WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE.equals(tokenUsage)
168 || tokenUsage.getName().contains("Endorsing")) {
169 return true;
170 }
171 }
172 return false;
173 }
174
175 private boolean isEndorsingToken(SecurityToken securityToken) throws XMLSecurityException {
176 SecurityToken rootToken = WSSUtils.getRootToken(securityToken);
177 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = rootToken.getTokenUsages();
178 for (int i = 0; i < tokenUsages.size(); i++) {
179 WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsages.get(i);
180 if (tokenUsage.getName().contains("Endorsing")) {
181 return true;
182 }
183 }
184 return false;
185 }
186
187 private boolean isSignedSupportingToken(SecurityToken securityToken) throws XMLSecurityException {
188 SecurityToken rootToken = WSSUtils.getRootToken(securityToken);
189 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = rootToken.getTokenUsages();
190 for (int i = 0; i < tokenUsages.size(); i++) {
191 WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsages.get(i);
192 if (tokenUsage.getName().contains("Signed")) {
193 return true;
194 }
195 }
196 return false;
197 }
198
199 private boolean isMainSignatureToken(SecurityToken securityToken) throws XMLSecurityException {
200 SecurityToken rootToken = WSSUtils.getRootToken(securityToken);
201 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = rootToken.getTokenUsages();
202 return tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
203 }
204
205 private boolean signsMainSignature(SecurityToken securityToken) throws XMLSecurityException {
206
207 List<QName> signaturePath = new LinkedList<>();
208 if (soap12) {
209 signaturePath.addAll(WSSConstants.SOAP_12_WSSE_SECURITY_HEADER_PATH);
210 } else {
211 signaturePath.addAll(WSSConstants.SOAP_11_WSSE_SECURITY_HEADER_PATH);
212 }
213 signaturePath.add(WSSConstants.TAG_dsig_Signature);
214
215 for (int i = 0; i < signedElementEvents.size(); i++) {
216 SignedElementSecurityEvent signedElementSecurityEvent = signedElementEvents.get(i);
217 if (WSSUtils.pathMatches(signedElementSecurityEvent.getElementPath(), signaturePath)) {
218 SecurityToken signingSecurityToken = getEffectiveSignatureToken(signedElementSecurityEvent.getSecurityToken());
219
220 if (signingSecurityToken != null && signingSecurityToken.getId().equals(securityToken.getId())) {
221 return true;
222 }
223 }
224 }
225 return false;
226 }
227
228 private boolean signsItsSignatureToken(SecurityToken securityToken) throws XMLSecurityException {
229 for (int i = 0; i < signedElementEvents.size(); i++) {
230 SignedElementSecurityEvent signedElementSecurityEvent = signedElementEvents.get(i);
231 if (WSSUtils.pathMatches(signedElementSecurityEvent.getElementPath(),
232 ((InboundSecurityToken)securityToken).getElementPath())) {
233
234 SecurityToken signingSecurityToken = signedElementSecurityEvent.getSecurityToken();
235 signingSecurityToken = getEffectiveSignatureToken(signingSecurityToken);
236
237 if (signingSecurityToken.getId().equals(securityToken.getId())) {
238
239
240 for (int j = 0; j < tokenSecurityEvents.size(); j++) {
241 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(j);
242 SecurityToken st = getEffectiveSignatureToken(tokenSecurityEvent.getSecurityToken());
243
244 if (signedElementSecurityEvent.getXmlSecEvent() == ((InboundSecurityToken)st).getXMLSecEvent()) {
245
246
247 if (st.getId().equals(securityToken.getId())) {
248 return true;
249 }
250 }
251 }
252 }
253 }
254 }
255 return false;
256 }
257
258 private boolean signsSignedSupportingTokens(SecurityToken securityToken) throws XMLSecurityException {
259
260 List<SecurityToken> signedSupportingTokens = new LinkedList<>();
261 List<SignedElementSecurityEvent> signedElements = new LinkedList<>();
262
263 for (int i = 0; i < tokenSecurityEvents.size(); i++) {
264 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
265 SecurityToken supportingToken = tokenSecurityEvent.getSecurityToken();
266 if (isSignedSupportingToken(supportingToken)) {
267 if (signedSupportingTokens.contains(supportingToken)) {
268 continue;
269 }
270 signedSupportingTokens.add(supportingToken);
271 List<QName> elementPath = ((InboundSecurityToken)supportingToken).getElementPath();
272
273 boolean found = false;
274 for (int j = 0; j < signedElementEvents.size(); j++) {
275 SignedElementSecurityEvent signedElementSecurityEvent = signedElementEvents.get(j);
276 if (WSSUtils.pathMatches(signedElementSecurityEvent.getElementPath(), elementPath)) {
277 SecurityToken elementSignatureToken = getEffectiveSignatureToken(signedElementSecurityEvent.getSecurityToken());
278
279 if (elementSignatureToken != null && elementSignatureToken.getId().equals(securityToken.getId())) {
280 if (!signedElements.contains(signedElementSecurityEvent)) {
281 signedElements.add(signedElementSecurityEvent);
282 }
283 found = true;
284 }
285 }
286 }
287 if (!found) {
288 return false;
289 }
290 }
291 }
292 return signedSupportingTokens.size() <= signedElements.size();
293 }
294
295 private SecurityToken getEffectiveSignatureToken(SecurityToken securityToken) throws XMLSecurityException {
296 SecurityToken tmp = WSSUtils.getRootToken(securityToken);
297 List<? extends SecurityToken> wrappedTokens = tmp.getWrappedTokens();
298 for (int i = 0; i < wrappedTokens.size(); i++) {
299 SecurityToken token = wrappedTokens.get(i);
300 if (isSignatureToken(token)) {
301
302
303 if (WSSecurityTokenConstants.DerivedKeyToken.equals(token.getTokenType())) {
304 return tmp;
305 }
306 tmp = token;
307 }
308 }
309 return tmp;
310 }
311 }