1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.processor;
21
22 import java.security.Principal;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26
27 import javax.crypto.SecretKey;
28
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.Node;
32
33 import org.apache.wss4j.common.bsp.BSPEnforcer;
34 import org.apache.wss4j.common.bsp.BSPRule;
35 import org.apache.wss4j.common.crypto.AlgorithmSuite;
36 import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator;
37 import org.apache.wss4j.common.ext.WSSecurityException;
38 import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal;
39 import org.apache.wss4j.common.token.SecurityTokenReference;
40 import org.apache.wss4j.common.util.KeyUtils;
41 import org.apache.wss4j.common.util.XMLUtils;
42 import org.apache.wss4j.dom.WSConstants;
43 import org.apache.wss4j.dom.WSDataRef;
44 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
45 import org.apache.wss4j.dom.handler.RequestData;
46 import org.apache.wss4j.dom.str.STRParser;
47 import org.apache.wss4j.dom.str.STRParserParameters;
48 import org.apache.wss4j.dom.str.STRParserResult;
49 import org.apache.wss4j.dom.str.SecurityTokenRefSTRParser;
50 import org.apache.wss4j.dom.util.EncryptionUtils;
51 import org.apache.wss4j.dom.util.SignatureUtils;
52 import org.apache.wss4j.dom.util.X509Util;
53
54 public class ReferenceListProcessor implements Processor {
55 private static final org.slf4j.Logger LOG =
56 org.slf4j.LoggerFactory.getLogger(ReferenceListProcessor.class);
57
58 public List<WSSecurityEngineResult> handleToken(
59 Element elem,
60 RequestData data
61 ) throws WSSecurityException {
62 LOG.debug("Found reference list element");
63 List<WSDataRef> dataRefs = handleReferenceList(elem, data);
64 WSSecurityEngineResult result =
65 new WSSecurityEngineResult(WSConstants.ENCR, dataRefs);
66 String tokenId = elem.getAttributeNS(null, "Id");
67 if (tokenId.length() != 0) {
68 result.put(WSSecurityEngineResult.TAG_ID, tokenId);
69 }
70 data.getWsDocInfo().addTokenElement(elem);
71 data.getWsDocInfo().addResult(result);
72 return Collections.singletonList(result);
73 }
74
75
76
77
78
79
80
81 private List<WSDataRef> handleReferenceList(
82 Element elem,
83 RequestData data
84 ) throws WSSecurityException {
85 List<WSDataRef> dataRefs = new ArrayList<>();
86 for (Node node = elem.getFirstChild();
87 node != null;
88 node = node.getNextSibling()
89 ) {
90 if (Node.ELEMENT_NODE == node.getNodeType()
91 && WSConstants.ENC_NS.equals(node.getNamespaceURI())
92 && "DataReference".equals(node.getLocalName())) {
93 String dataRefURI = ((Element) node).getAttributeNS(null, "URI");
94 dataRefURI = XMLUtils.getIDFromReference(dataRefURI);
95
96
97 if (!data.getWsDocInfo().hasResult(WSConstants.ENCR, dataRefURI)) {
98 WSDataRef dataRef =
99 decryptDataRefEmbedded(elem.getOwnerDocument(), dataRefURI, data);
100 dataRefs.add(dataRef);
101 }
102 }
103 }
104
105 return dataRefs;
106 }
107
108
109
110
111
112 private WSDataRef decryptDataRefEmbedded(
113 Document doc,
114 String dataRefURI,
115 RequestData data
116 ) throws WSSecurityException {
117 LOG.debug("Found data reference: {}", dataRefURI);
118
119
120
121 Element encryptedDataElement =
122 EncryptionUtils.findEncryptedDataElement(data.getWsDocInfo(), dataRefURI);
123
124 if (encryptedDataElement != null && data.isRequireSignedEncryptedDataElements()) {
125 List<WSSecurityEngineResult> signedResults =
126 data.getWsDocInfo().getResultsByTag(WSConstants.SIGN);
127 SignatureUtils.verifySignedElement(encryptedDataElement, signedResults);
128 }
129
130
131
132 String symEncAlgo = X509Util.getEncAlgo(encryptedDataElement);
133 Element keyInfoElement =
134 XMLUtils.getDirectChildElement(
135 encryptedDataElement, "KeyInfo", WSConstants.SIG_NS
136 );
137
138 if (keyInfoElement == null) {
139 throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "noKeyinfo");
140 }
141
142 checkBSPCompliance(keyInfoElement, symEncAlgo, data.getBSPEnforcer());
143
144
145
146
147
148 Element secRefToken =
149 XMLUtils.getDirectChildElement(
150 keyInfoElement, "SecurityTokenReference", WSConstants.WSSE_NS
151 );
152 SecretKey symmetricKey = null;
153 Principal principal = null;
154 if (secRefToken == null) {
155 byte[] decryptedData =
156 X509Util.getSecretKey(keyInfoElement, symEncAlgo, data.getCallbackHandler());
157 symmetricKey = KeyUtils.prepareSecretKey(symEncAlgo, decryptedData);
158 } else {
159 STRParserParameters parameters = new STRParserParameters();
160 parameters.setData(data);
161 parameters.setStrElement(secRefToken);
162 if (symEncAlgo != null) {
163 parameters.setDerivationKeyLength(KeyUtils.getKeyLength(symEncAlgo));
164 }
165
166 STRParser strParser = new SecurityTokenRefSTRParser();
167 STRParserResult parserResult = strParser.parseSecurityTokenReference(parameters);
168 byte[] secretKey = parserResult.getSecretKey();
169 principal = parserResult.getPrincipal();
170 symmetricKey = KeyUtils.prepareSecretKey(symEncAlgo, secretKey);
171 }
172
173
174 AlgorithmSuite algorithmSuite = data.getAlgorithmSuite();
175 if (algorithmSuite != null) {
176 AlgorithmSuiteValidator algorithmSuiteValidator = new
177 AlgorithmSuiteValidator(algorithmSuite);
178
179 if (principal instanceof WSDerivedKeyTokenPrincipal) {
180 algorithmSuiteValidator.checkDerivedKeyAlgorithm(
181 ((WSDerivedKeyTokenPrincipal)principal).getAlgorithm()
182 );
183 algorithmSuiteValidator.checkEncryptionDerivedKeyLength(
184 ((WSDerivedKeyTokenPrincipal)principal).getLength()
185 );
186 }
187
188 algorithmSuiteValidator.checkSymmetricKeyLength(symmetricKey.getEncoded().length);
189 algorithmSuiteValidator.checkSymmetricEncryptionAlgorithm(symEncAlgo);
190 }
191
192 return
193 EncryptionUtils.decryptEncryptedData(
194 doc, dataRefURI, encryptedDataElement, symmetricKey, symEncAlgo, data.getAttachmentCallbackHandler(),
195 data.getEncryptionSerializer()
196 );
197 }
198
199
200
201
202
203
204
205 private static void checkBSPCompliance(
206 Element keyInfoElement,
207 String encAlgo,
208 BSPEnforcer bspEnforcer
209 ) throws WSSecurityException {
210
211 int result = 0;
212 Node node = keyInfoElement.getFirstChild();
213 Element child = null;
214 while (node != null) {
215 if (Node.ELEMENT_NODE == node.getNodeType()) {
216 result++;
217 child = (Element)node;
218 }
219 node = node.getNextSibling();
220 }
221 if (result != 1) {
222 bspEnforcer.handleBSPRule(BSPRule.R5424);
223 }
224
225 if (child == null || !WSConstants.WSSE_NS.equals(child.getNamespaceURI())
226 || !SecurityTokenReference.SECURITY_TOKEN_REFERENCE.equals(child.getLocalName())) {
227 bspEnforcer.handleBSPRule(BSPRule.R5426);
228 }
229
230
231 if (encAlgo == null) {
232 bspEnforcer.handleBSPRule(BSPRule.R5601);
233 }
234
235 if (!WSConstants.TRIPLE_DES.equals(encAlgo)
236 && !WSConstants.AES_128.equals(encAlgo)
237 && !WSConstants.AES_128_GCM.equals(encAlgo)
238 && !WSConstants.AES_256.equals(encAlgo)
239 && !WSConstants.AES_256_GCM.equals(encAlgo)) {
240 bspEnforcer.handleBSPRule(BSPRule.R5620);
241 }
242 }
243
244 }
245