1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.saml.ext;
21
22 import javax.xml.namespace.QName;
23
24 import org.apache.ws.security.WSSecurityException;
25 import org.opensaml.xml.*;
26 import org.opensaml.xml.io.*;
27 import org.opensaml.xml.signature.Signature;
28 import org.opensaml.xml.signature.SignatureException;
29 import org.opensaml.xml.signature.Signer;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.DocumentFragment;
32 import org.w3c.dom.Element;
33
34
35
36
37
38
39 public final class OpenSAMLUtil {
40 private static final org.apache.commons.logging.Log LOG =
41 org.apache.commons.logging.LogFactory.getLog(OpenSAMLUtil.class);
42
43 private static XMLObjectBuilderFactory builderFactory;
44 private static MarshallerFactory marshallerFactory;
45 private static UnmarshallerFactory unmarshallerFactory;
46 private static boolean samlEngineInitialized = false;
47
48 private OpenSAMLUtil() {
49
50 }
51
52
53
54
55 public static synchronized void initSamlEngine() {
56 if (!samlEngineInitialized) {
57 if (LOG.isDebugEnabled()) {
58 LOG.debug("Initializing the opensaml2 library...");
59 }
60 try {
61 OpenSAMLBootstrap.bootstrap();
62 builderFactory = Configuration.getBuilderFactory();
63 marshallerFactory = Configuration.getMarshallerFactory();
64 unmarshallerFactory = Configuration.getUnmarshallerFactory();
65 samlEngineInitialized = true;
66 if (LOG.isDebugEnabled()) {
67 LOG.debug("opensaml2 library bootstrap complete");
68 }
69 } catch (ConfigurationException e) {
70 LOG.error(
71 "Unable to bootstrap the opensaml2 library - all SAML operations will fail",
72 e
73 );
74 }
75 }
76 }
77
78
79
80
81
82
83
84
85 public static XMLObject fromDom(Element root) throws WSSecurityException {
86 if (root == null) {
87 LOG.debug("Attempting to unmarshal a null element!");
88 throw new WSSecurityException("Error unmarshalling a SAML assertion");
89 }
90 Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(root);
91 if (unmarshaller == null) {
92 LOG.debug("Unable to find an unmarshaller for element: " + root.getLocalName());
93 throw new WSSecurityException("Error unmarshalling a SAML assertion");
94 }
95 try {
96 return unmarshaller.unmarshall(root);
97 } catch (UnmarshallingException ex) {
98 throw new WSSecurityException("Error unmarshalling a SAML assertion", ex);
99 }
100 }
101
102
103
104
105
106
107
108
109
110
111 public static Element toDom(
112 XMLObject xmlObject,
113 Document doc
114 ) throws WSSecurityException {
115 return toDom(xmlObject, doc, true);
116 }
117
118
119
120
121
122
123
124
125
126
127
128 public static Element toDom(
129 XMLObject xmlObject,
130 Document doc,
131 boolean signObject
132 ) throws WSSecurityException {
133 Marshaller marshaller = marshallerFactory.getMarshaller(xmlObject);
134 Element element = null;
135 DocumentFragment frag = doc == null ? null : doc.createDocumentFragment();
136 try {
137 if (frag != null) {
138 String ns = null;
139 String nm = null;
140 if (doc.getDocumentElement() != null) {
141 ns = doc.getDocumentElement().getNamespaceURI();
142 nm = doc.getDocumentElement().getLocalName();
143 }
144 while (doc.getFirstChild() != null) {
145 frag.appendChild(doc.removeChild(doc.getFirstChild()));
146 }
147 if (nm != null) {
148 doc.appendChild(doc.createElementNS(ns, nm));
149 }
150 }
151 try {
152 if (doc == null) {
153 element = marshaller.marshall(xmlObject);
154 } else if (doc.getDocumentElement() == null) {
155 element = marshaller.marshall(xmlObject, doc);
156 } else {
157 element = marshaller.marshall(xmlObject, doc.getDocumentElement());
158 }
159 } catch (MarshallingException ex) {
160 throw new WSSecurityException("Error marshalling a SAML assertion", ex);
161 }
162
163 if (signObject) {
164 signXMLObject(xmlObject);
165 }
166 } finally {
167 if (frag != null) {
168 if (doc.getDocumentElement() != null
169 && doc.getDocumentElement() != element) {
170 doc.getDocumentElement().removeChild(element);
171 }
172 while (doc.getFirstChild() != null) {
173 doc.removeChild(doc.getFirstChild());
174 }
175 doc.appendChild(frag);
176 doc.getDocumentElement();
177 }
178 }
179 return element;
180 }
181
182 private static void signXMLObject(XMLObject xmlObject) throws WSSecurityException {
183 if (xmlObject instanceof org.opensaml.saml1.core.Response) {
184 org.opensaml.saml1.core.Response response =
185 (org.opensaml.saml1.core.Response)xmlObject;
186
187
188 if (response.getAssertions() != null) {
189 for (org.opensaml.saml1.core.Assertion assertion : response.getAssertions()) {
190 signObject(assertion.getSignature());
191 }
192 }
193
194 signObject(response.getSignature());
195 } else if (xmlObject instanceof org.opensaml.saml2.core.Response) {
196 org.opensaml.saml2.core.Response response =
197 (org.opensaml.saml2.core.Response)xmlObject;
198
199
200 if (response.getAssertions() != null) {
201 for (org.opensaml.saml2.core.Assertion assertion : response.getAssertions()) {
202 signObject(assertion.getSignature());
203 }
204 }
205
206 signObject(response.getSignature());
207 } else if (xmlObject instanceof org.opensaml.saml2.core.Assertion) {
208 org.opensaml.saml2.core.Assertion saml2 =
209 (org.opensaml.saml2.core.Assertion) xmlObject;
210
211 signObject(saml2.getSignature());
212 } else if (xmlObject instanceof org.opensaml.saml1.core.Assertion) {
213 org.opensaml.saml1.core.Assertion saml1 =
214 (org.opensaml.saml1.core.Assertion) xmlObject;
215
216 signObject(saml1.getSignature());
217 } else if (xmlObject instanceof org.opensaml.saml2.core.RequestAbstractType) {
218 org.opensaml.saml2.core.RequestAbstractType request =
219 (org.opensaml.saml2.core.RequestAbstractType) xmlObject;
220
221
222 signObject(request.getSignature());
223 } else if (xmlObject instanceof org.opensaml.saml1.core.Request) {
224 org.opensaml.saml1.core.Request request =
225 (org.opensaml.saml1.core.Request) xmlObject;
226
227 signObject(request.getSignature());
228 }
229 }
230
231 private static void signObject(Signature signature) throws WSSecurityException {
232 if (signature != null) {
233 try {
234 Signer.signObject(signature);
235 } catch (SignatureException ex) {
236 throw new WSSecurityException("Error signing a SAML assertion", ex);
237 }
238 }
239 }
240
241
242
243
244
245
246 @SuppressWarnings("unchecked")
247 public static Signature buildSignature() {
248 QName qName = Signature.DEFAULT_ELEMENT_NAME;
249 XMLObjectBuilder<Signature> builder = builderFactory.getBuilder(qName);
250 if (builder == null) {
251 LOG.error(
252 "Unable to retrieve builder for object QName "
253 + qName
254 );
255 return null;
256 }
257 return
258 (Signature)builder.buildObject(
259 qName.getNamespaceURI(), qName.getLocalPart(), qName.getPrefix()
260 );
261 }
262
263
264
265
266
267
268
269 public static boolean isMethodSenderVouches(String confirmMethod) {
270 return
271 confirmMethod != null && confirmMethod.startsWith("urn:oasis:names:tc:SAML:")
272 && confirmMethod.endsWith(":cm:sender-vouches");
273 }
274
275
276
277
278
279
280
281 public static boolean isMethodHolderOfKey(String confirmMethod) {
282 return
283 confirmMethod != null && confirmMethod.startsWith("urn:oasis:names:tc:SAML:")
284 && confirmMethod.endsWith(":cm:holder-of-key");
285 }
286
287 }