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.wss4j.policy.AssertionState;
22 import org.apache.wss4j.policy.SPConstants;
23 import org.apache.wss4j.common.WSSPolicyException;
24 import org.apache.wss4j.policy.model.AbstractSecurityAssertion;
25 import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
26 import org.apache.xml.security.exceptions.XMLSecurityException;
27 import org.apache.xml.security.stax.securityEvent.EncryptedElementSecurityEvent;
28 import org.apache.xml.security.stax.securityEvent.SecurityEvent;
29 import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
30 import org.apache.xml.security.stax.securityEvent.TokenSecurityEvent;
31 import org.apache.xml.security.stax.securityToken.SecurityToken;
32 import org.apache.wss4j.policy.stax.Assertable;
33 import org.apache.wss4j.policy.stax.DummyPolicyAsserter;
34 import org.apache.wss4j.policy.stax.PolicyAsserter;
35 import org.apache.wss4j.stax.ext.WSSConstants;
36 import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
37 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
38 import org.apache.wss4j.stax.utils.WSSUtils;
39
40 import javax.xml.namespace.QName;
41
42 import java.util.ArrayList;
43 import java.util.Iterator;
44 import java.util.LinkedList;
45 import java.util.List;
46
47
48
49
50 public class SignatureProtectionAssertionState extends AssertionState implements Assertable {
51
52 private final List<EncryptedElementSecurityEvent> encryptedElementEvents = new ArrayList<>();
53 private final List<TokenSecurityEvent<? extends SecurityToken>> tokenSecurityEvents = new ArrayList<>();
54 private final List<List<QName>> elementPaths = new ArrayList<>();
55 private PolicyAsserter policyAsserter;
56
57 public SignatureProtectionAssertionState(AbstractSecurityAssertion assertion,
58 PolicyAsserter policyAsserter,
59 boolean asserted) {
60 super(assertion, asserted);
61 List<QName> signature11Path = new LinkedList<>();
62 signature11Path.addAll(WSSConstants.SOAP_11_HEADER_PATH);
63 signature11Path.add(WSSConstants.TAG_WSSE_SECURITY);
64 signature11Path.add(WSSConstants.TAG_dsig_Signature);
65 elementPaths.add(signature11Path);
66
67 List<QName> signatureConfirmation11Path = new LinkedList<>();
68 signatureConfirmation11Path.addAll(WSSConstants.SOAP_11_HEADER_PATH);
69 signatureConfirmation11Path.add(WSSConstants.TAG_WSSE_SECURITY);
70 signatureConfirmation11Path.add(WSSConstants.TAG_WSSE11_SIG_CONF);
71 elementPaths.add(signatureConfirmation11Path);
72
73 this.policyAsserter = policyAsserter;
74 if (this.policyAsserter == null) {
75 this.policyAsserter = new DummyPolicyAsserter();
76 }
77
78 if (asserted) {
79 String namespace = getAssertion().getName().getNamespaceURI();
80 policyAsserter.assertPolicy(new QName(namespace, SPConstants.ENCRYPT_SIGNATURE));
81 }
82 }
83
84 @Override
85 public SecurityEventConstants.Event[] getSecurityEventType() {
86 return new SecurityEventConstants.Event[]{
87 WSSecurityEventConstants.EncryptedElement,
88 WSSecurityEventConstants.EncryptedKeyToken,
89 WSSecurityEventConstants.ISSUED_TOKEN,
90 WSSecurityEventConstants.KERBEROS_TOKEN,
91 SecurityEventConstants.KeyValueToken,
92 WSSecurityEventConstants.REL_TOKEN,
93 WSSecurityEventConstants.SAML_TOKEN,
94 WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
95 WSSecurityEventConstants.USERNAME_TOKEN,
96 SecurityEventConstants.X509Token,
97 WSSecurityEventConstants.OPERATION,
98 };
99 }
100
101 @Override
102 public boolean assertEvent(SecurityEvent securityEvent) throws WSSPolicyException {
103 if (securityEvent instanceof EncryptedElementSecurityEvent) {
104 EncryptedElementSecurityEvent encryptedElementSecurityEvent =
105 (EncryptedElementSecurityEvent) securityEvent;
106
107 Iterator<List<QName>> pathElementsIterator = elementPaths.iterator();
108 while (pathElementsIterator.hasNext()) {
109 List<QName> qNameList = pathElementsIterator.next();
110 if (WSSUtils.pathMatches(qNameList, encryptedElementSecurityEvent.getElementPath())) {
111 encryptedElementEvents.add(encryptedElementSecurityEvent);
112 }
113 }
114 } else if (securityEvent instanceof TokenSecurityEvent) {
115 @SuppressWarnings("unchecked")
116 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent
117 = (TokenSecurityEvent<? extends SecurityToken>) securityEvent;
118 tokenSecurityEvents.add(tokenSecurityEvent);
119 }
120
121 return true;
122 }
123
124 @Override
125 public boolean isAsserted() {
126 clearErrorMessage();
127
128
129 if (encryptedElementEvents.size() == 1) {
130 return testEncryptedSignature(encryptedElementEvents.get(0));
131 } else if (encryptedElementEvents.size() > 1) {
132
133 String endorsingSignatureId = findEndorsingSignatureId();
134 for (EncryptedElementSecurityEvent encryptedElementSecurityEvent : encryptedElementEvents) {
135 String elementId = encryptedElementSecurityEvent.getCorrelationID();
136 if (endorsingSignatureId != null && endorsingSignatureId.equals(elementId)) {
137
138 continue;
139 }
140 if (!testEncryptedSignature(encryptedElementSecurityEvent)) {
141 return false;
142 }
143 }
144 }
145
146 return true;
147 }
148
149 private String findEndorsingSignatureId() {
150 for (int i = 0; i < tokenSecurityEvents.size(); i++) {
151 TokenSecurityEvent<? extends SecurityToken> tokenSecurityEvent = tokenSecurityEvents.get(i);
152 try {
153 SecurityToken securityToken =
154 getEffectiveSignatureToken(tokenSecurityEvent.getSecurityToken());
155 if (isSignatureToken(securityToken) && !isMainSignatureToken(securityToken)) {
156 return tokenSecurityEvent.getCorrelationID();
157 }
158 } catch (XMLSecurityException e) {
159
160 return null;
161 }
162 }
163 return null;
164 }
165
166 private boolean isSignatureToken(SecurityToken securityToken) {
167 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = securityToken.getTokenUsages();
168 for (int i = 0; i < tokenUsages.size(); i++) {
169 WSSecurityTokenConstants.TokenUsage tokenUsage = tokenUsages.get(i);
170 if (WSSecurityTokenConstants.TokenUsage_Signature.equals(tokenUsage)
171 || WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE.equals(tokenUsage)
172 || tokenUsage.getName().contains("Endorsing")) {
173 return true;
174 }
175 }
176 return false;
177 }
178
179 private boolean isMainSignatureToken(SecurityToken securityToken) throws XMLSecurityException {
180 SecurityToken rootToken = WSSUtils.getRootToken(securityToken);
181 List<WSSecurityTokenConstants.TokenUsage> tokenUsages = rootToken.getTokenUsages();
182 return tokenUsages.contains(WSSecurityTokenConstants.TOKENUSAGE_MAIN_SIGNATURE);
183 }
184
185 private SecurityToken getEffectiveSignatureToken(SecurityToken securityToken) throws XMLSecurityException {
186 SecurityToken tmp = WSSUtils.getRootToken(securityToken);
187 List<? extends SecurityToken> wrappedTokens = tmp.getWrappedTokens();
188 for (int i = 0; i < wrappedTokens.size(); i++) {
189 SecurityToken token = wrappedTokens.get(i);
190 if (isSignatureToken(token)) {
191
192
193 if (WSSecurityTokenConstants.DerivedKeyToken.equals(token.getTokenType())) {
194 return tmp;
195 }
196 tmp = token;
197 }
198 }
199 return tmp;
200 }
201
202 private boolean testEncryptedSignature(EncryptedElementSecurityEvent encryptedElementSecurityEvent) {
203 AbstractSymmetricAsymmetricBinding abstractSymmetricAsymmetricBinding =
204 (AbstractSymmetricAsymmetricBinding) getAssertion();
205
206 String namespace = getAssertion().getName().getNamespaceURI();
207
208 if (encryptedElementSecurityEvent.isEncrypted()) {
209 if (abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
210 setAsserted(true);
211 policyAsserter.assertPolicy(new QName(namespace, SPConstants.ENCRYPT_SIGNATURE));
212 return true;
213 } else {
214 setAsserted(false);
215 setErrorMessage("Element " + WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath())
216 + " must not be encrypted");
217 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.ENCRYPT_SIGNATURE),
218 getErrorMessage());
219 return false;
220 }
221 } else {
222 if (abstractSymmetricAsymmetricBinding.isEncryptSignature()) {
223 setAsserted(false);
224 setErrorMessage("Element " + WSSUtils.pathAsString(encryptedElementSecurityEvent.getElementPath())
225 + " must be encrypted");
226 policyAsserter.unassertPolicy(new QName(namespace, SPConstants.ENCRYPT_SIGNATURE),
227 getErrorMessage());
228 return false;
229 } else {
230 setAsserted(true);
231 policyAsserter.assertPolicy(new QName(namespace, SPConstants.ENCRYPT_SIGNATURE));
232 return true;
233 }
234 }
235 }
236
237 }