1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.common.impl;
18
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Set;
22
23 import org.apache.xml.security.signature.XMLSignature;
24 import org.apache.xml.security.signature.XMLSignatureException;
25 import org.apache.xml.security.transforms.Transform;
26 import org.apache.xml.security.transforms.TransformationException;
27 import org.apache.xml.security.transforms.Transforms;
28 import org.apache.xml.security.transforms.params.InclusiveNamespaces;
29 import org.opensaml.common.SignableSAMLObject;
30 import org.opensaml.xml.Configuration;
31 import org.opensaml.xml.Namespace;
32 import org.opensaml.xml.XMLObject;
33 import org.opensaml.xml.security.SecurityConfiguration;
34 import org.opensaml.xml.signature.ContentReference;
35 import org.opensaml.xml.signature.SignatureConstants;
36 import org.opensaml.xml.util.DatatypeHelper;
37 import org.opensaml.xml.util.LazyList;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class SAMLObjectContentReference implements ContentReference {
71
72
73 private final Logger log = LoggerFactory.getLogger(SAMLObjectContentReference.class);
74
75
76 private SignableSAMLObject signableObject;
77
78
79 private String digestAlgorithm;
80
81
82 private List<String> transforms;
83
84
85
86
87
88
89 public SAMLObjectContentReference(SignableSAMLObject newSignableObject) {
90 signableObject = newSignableObject;
91 transforms = new LazyList<String>();
92
93
94 if (Configuration.getGlobalSecurityConfiguration() != null ) {
95 digestAlgorithm = Configuration.getGlobalSecurityConfiguration().getSignatureReferenceDigestMethod();
96 }
97 if (digestAlgorithm == null) {
98 digestAlgorithm = SignatureConstants.ALGO_ID_DIGEST_SHA1;
99 }
100
101 transforms.add(SignatureConstants.TRANSFORM_ENVELOPED_SIGNATURE);
102 transforms.add(SignatureConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
103 }
104
105
106
107
108
109
110 public List<String> getTransforms() {
111 return transforms;
112 }
113
114
115
116
117
118
119 public String getDigestAlgorithm() {
120 return digestAlgorithm;
121 }
122
123
124
125
126
127
128 public void setDigestAlgorithm(String newAlgorithm) {
129 digestAlgorithm = newAlgorithm;
130 }
131
132
133 public void createReference(XMLSignature signature) {
134 try {
135 Transforms dsigTransforms = new Transforms(signature.getDocument());
136 for (int i=0; i<transforms.size(); i++) {
137 String transform = transforms.get(i);
138 dsigTransforms.addTransform(transform);
139
140 if (transform.equals(SignatureConstants.TRANSFORM_C14N_EXCL_WITH_COMMENTS) ||
141 transform.equals(SignatureConstants.TRANSFORM_C14N_EXCL_OMIT_COMMENTS)) {
142
143 processExclusiveTransform(signature, dsigTransforms.item(i));
144
145 }
146 }
147
148 if ( ! DatatypeHelper.isEmpty(signableObject.getSignatureReferenceID()) ) {
149 signature.addDocument("#" + signableObject.getSignatureReferenceID(), dsigTransforms, digestAlgorithm);
150 } else {
151 log.debug("SignableSAMLObject had no reference ID, signing using whole document Reference URI");
152 signature.addDocument("" , dsigTransforms, digestAlgorithm);
153 }
154
155 } catch (TransformationException e) {
156 log.error("Unsupported signature transformation", e);
157 } catch (XMLSignatureException e) {
158 log.error("Error adding content reference to signature", e);
159 }
160 }
161
162
163
164
165
166
167
168 private void processExclusiveTransform(XMLSignature signature, Transform transform) {
169
170
171
172 log.debug("Adding list of inclusive namespaces for signature exclusive canonicalization transform");
173 HashSet<String> inclusiveNamespacePrefixes = new HashSet<String>();
174 populateNamespacePrefixes(inclusiveNamespacePrefixes, signableObject);
175
176 if (inclusiveNamespacePrefixes != null && inclusiveNamespacePrefixes.size() > 0) {
177 InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(signature.getDocument(),
178 inclusiveNamespacePrefixes);
179 transform.getElement().appendChild(inclusiveNamespaces.getElement());
180 }
181 }
182
183
184
185
186
187
188
189 private void populateNamespacePrefixes(Set<String> namespacePrefixes, XMLObject signatureContent) {
190 if (signatureContent.getNamespaces() != null) {
191 for (Namespace namespace : signatureContent.getNamespaces()) {
192 if (namespace != null) {
193 String namespacePrefix = namespace.getNamespacePrefix();
194
195
196
197 if (namespacePrefix == null) {
198 namespacePrefix = "xmlns";
199 }
200 namespacePrefixes.add(namespacePrefix);
201 }
202 }
203 }
204
205 if (signatureContent.getOrderedChildren() != null) {
206 for (XMLObject xmlObject : signatureContent.getOrderedChildren()) {
207 if (xmlObject != null) {
208 populateNamespacePrefixes(namespacePrefixes, xmlObject);
209 }
210 }
211 }
212 }
213 }