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 while (doc.getFirstChild() != null) {
139 frag.appendChild(doc.removeChild(doc.getFirstChild()));
140 }
141 }
142 try {
143 if (doc == null) {
144 element = marshaller.marshall(xmlObject);
145 } else {
146 element = marshaller.marshall(xmlObject, doc);
147 }
148 } catch (MarshallingException ex) {
149 throw new WSSecurityException("Error marshalling a SAML assertion", ex);
150 }
151
152 if (signObject) {
153 signXMLObject(xmlObject);
154 }
155 } finally {
156 if (frag != null) {
157 while (doc.getFirstChild() != null) {
158 doc.removeChild(doc.getFirstChild());
159 }
160 doc.appendChild(frag);
161 }
162 }
163 return element;
164 }
165
166 private static void signXMLObject(XMLObject xmlObject) throws WSSecurityException {
167 if (xmlObject instanceof org.opensaml.saml1.core.Response) {
168 org.opensaml.saml1.core.Response response =
169 (org.opensaml.saml1.core.Response)xmlObject;
170
171
172 if (response.getAssertions() != null) {
173 for (org.opensaml.saml1.core.Assertion assertion : response.getAssertions()) {
174 signObject(assertion.getSignature());
175 }
176 }
177
178 signObject(response.getSignature());
179 } else if (xmlObject instanceof org.opensaml.saml2.core.Response) {
180 org.opensaml.saml2.core.Response response =
181 (org.opensaml.saml2.core.Response)xmlObject;
182
183
184 if (response.getAssertions() != null) {
185 for (org.opensaml.saml2.core.Assertion assertion : response.getAssertions()) {
186 signObject(assertion.getSignature());
187 }
188 }
189
190 signObject(response.getSignature());
191 } else if (xmlObject instanceof org.opensaml.saml2.core.Assertion) {
192 org.opensaml.saml2.core.Assertion saml2 =
193 (org.opensaml.saml2.core.Assertion) xmlObject;
194
195 signObject(saml2.getSignature());
196 } else if (xmlObject instanceof org.opensaml.saml1.core.Assertion) {
197 org.opensaml.saml1.core.Assertion saml1 =
198 (org.opensaml.saml1.core.Assertion) xmlObject;
199
200 signObject(saml1.getSignature());
201 } else if (xmlObject instanceof org.opensaml.saml2.core.RequestAbstractType) {
202 org.opensaml.saml2.core.RequestAbstractType request =
203 (org.opensaml.saml2.core.RequestAbstractType) xmlObject;
204
205
206 signObject(request.getSignature());
207 } else if (xmlObject instanceof org.opensaml.saml1.core.Request) {
208 org.opensaml.saml1.core.Request request =
209 (org.opensaml.saml1.core.Request) xmlObject;
210
211 signObject(request.getSignature());
212 }
213 }
214
215 private static void signObject(Signature signature) throws WSSecurityException {
216 if (signature != null) {
217 try {
218 Signer.signObject(signature);
219 } catch (SignatureException ex) {
220 throw new WSSecurityException("Error signing a SAML assertion", ex);
221 }
222 }
223 }
224
225
226
227
228
229
230 @SuppressWarnings("unchecked")
231 public static Signature buildSignature() {
232 QName qName = Signature.DEFAULT_ELEMENT_NAME;
233 XMLObjectBuilder<Signature> builder = builderFactory.getBuilder(qName);
234 if (builder == null) {
235 LOG.error(
236 "Unable to retrieve builder for object QName "
237 + qName
238 );
239 return null;
240 }
241 return
242 (Signature)builder.buildObject(
243 qName.getNamespaceURI(), qName.getLocalPart(), qName.getPrefix()
244 );
245 }
246
247
248
249
250
251
252
253 public static boolean isMethodSenderVouches(String confirmMethod) {
254 return
255 confirmMethod != null && confirmMethod.startsWith("urn:oasis:names:tc:SAML:")
256 && confirmMethod.endsWith(":cm:sender-vouches");
257 }
258
259
260
261
262
263
264
265 public static boolean isMethodHolderOfKey(String confirmMethod) {
266 return
267 confirmMethod != null && confirmMethod.startsWith("urn:oasis:names:tc:SAML:")
268 && confirmMethod.endsWith(":cm:holder-of-key");
269 }
270
271 }