1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package dk.sosi.seal.model;
31
32 import dk.sosi.seal.model.constants.*;
33 import dk.sosi.seal.modelbuilders.ModelBuildException;
34 import dk.sosi.seal.pki.Federation;
35 import dk.sosi.seal.xml.XmlUtil;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.Node;
39 import org.w3c.dom.NodeList;
40
41 import java.text.ParseException;
42 import java.util.Date;
43 import java.util.LinkedList;
44 import java.util.List;
45
46
47
48
49
50 public class LibertyRequest extends AbstractDOMInfoExtractor {
51
52 public LibertyRequest(Federation federation, Document doc) {
53 this.dom = doc.getDocumentElement();
54 final IdentityToken identityToken = getIdentityToken();
55 identityToken.validateSignature(federation);
56
57 validateLibertySignature(federation);
58
59 final Date now = new Date();
60 if (now.before(identityToken.getNotBefore()) || ! now.before(identityToken.getNotOnOrAfter())) {
61 validateLibertyTimestamp(identityToken);
62 }
63 }
64
65 public IdentityToken getIdentityToken() {
66 final Element assertion = getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, SAMLTags.assertion);
67 if (assertion == null) {
68 throw new ModelBuildException("Could not find SAML assertion element");
69 }
70 return new IdentityToken(assertion);
71 }
72
73 public Date getCreatedTimestamp() {
74 final Element createdTimestamp = getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, WSUTags.timestamp, WSUTags.created);
75 if (createdTimestamp == null) {
76 throw new ModelBuildException("Could not find wsu:Created element");
77 }
78 try {
79 return XmlUtil.fromXMLTimeStamp(createdTimestamp.getTextContent());
80 } catch (ParseException e) {
81 throw new ModelBuildException("Could not parse wsu:Created element", e);
82 }
83 }
84
85 public String getMessageID() {
86 final Element messageID = getTag(SOAPTags.envelope, SOAPTags.header, WSATags.messageID);
87 if (messageID == null) {
88 throw new ModelBuildException("Could not find " + NameSpaces.WSA_1_0_SCHEMA + "#MessageID element");
89 }
90 return messageID.getTextContent();
91 }
92
93 private void validateLibertySignature(Federation federation) {
94 final Element signatureElement = getLibertySignatureElement();
95 if ( ! SignatureUtil.validate(signatureElement, federation, null, true)) {
96 throw new ModelBuildException("Liberty signature could not be validated");
97 }
98
99 final NodeList references = signatureElement.getElementsByTagNameNS(NameSpaces.DSIG_SCHEMA, DSTags.REFERENCE);
100 final List<Element> dereferencedSignedElements = dereference(references);
101
102 final Element messageID = getWSAddressingMessageIDElement();
103 validateIsReferenced(messageID, dereferencedSignedElements);
104
105 final Element action = getWSAddressingActionElement();
106 validateIsReferenced(action, dereferencedSignedElements);
107
108 final Element to = getWSAddressingToElement();
109 if (to != null) {
110 validateIsReferenced(to, dereferencedSignedElements);
111 }
112
113 final Element framework = getLibertyFrameworkElement();
114 validateIsReferenced(framework, dereferencedSignedElements);
115
116 final Element timestamp = getTimestampElement();
117 validateIsReferenced(timestamp, dereferencedSignedElements);
118
119 final Element securityTokenReference = getSecurityTokenReferenceElement();
120 validateIsReferenced(securityTokenReference, dereferencedSignedElements);
121 validateReferenceToIdentityToken(securityTokenReference);
122
123 final Element bodyElement = getBodyElement();
124 validateIsReferenced(bodyElement, dereferencedSignedElements);
125 }
126
127 private List<Element> dereference(NodeList references) {
128 final LinkedList<Element> elements = new LinkedList<Element>();
129 for (int i = 0; i < references.getLength(); i++) {
130 final Element reference = (Element) references.item(i);
131 final String uri = reference.getAttribute(DSAttributes.URI);
132 final Element element = (Element) XmlUtil.getElementByIdExtended(dom, uri.substring(1));
133 if (element != null) {
134 elements.add(element);
135 }
136 }
137 return elements;
138 }
139
140 private void validateReferenceToIdentityToken(Element securityTokenReference) {
141 final Element keyIdentifier = XmlUtil.getFirstChildElementNS(securityTokenReference, NameSpaces.WSSE_SCHEMA, WSSETags.KEY_IDENTIFIER);
142 if (keyIdentifier == null) {
143 throw new ModelBuildException("Could not find KeyIdentifier element in SecurityTokenReference");
144 }
145 final Node token = XmlUtil.getElementByIdExtended(dom, keyIdentifier.getTextContent());
146 if (! getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, SAMLTags.assertion).equals(token)) {
147 throw new ModelBuildException("SecurityTokenReference is not referencing IdentityToken");
148 }
149 }
150
151 private void validateLibertyTimestamp(IdentityToken identityToken) {
152 if (getCreatedTimestamp().before(identityToken.getNotBefore()) || getCreatedTimestamp().after(identityToken.getNotOnOrAfter())) {
153 throw new ModelBuildException("Liberty timestamp (wsu:Created) is not within the Identity Tokens validity period");
154 }
155 }
156
157 private void validateIsReferenced(Element element, List<Element> references) {
158 if (! references.contains(element)) {
159 throw new ModelBuildException("Missing Liberty signature on element " + element.getNamespaceURI() + "#" + element.getLocalName());
160 }
161 }
162
163 private Element getLibertySignatureElement() {
164 final Element signature = getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, DSTags.signature);
165 if (signature == null) {
166 throw new ModelBuildException("Could not find Liberty signature element");
167 }
168 return signature;
169 }
170
171 private Element getWSAddressingMessageIDElement() {
172 final Element messageID = getTag(SOAPTags.envelope, SOAPTags.header, WSATags.messageID);
173 if (messageID == null) {
174 throw new ModelBuildException("Could not find WS-Addressing 1.0 MessageID element");
175 }
176 return messageID;
177 }
178
179
180 private Element getWSAddressingActionElement() {
181 final Element action = getTag(SOAPTags.envelope, SOAPTags.header, WSATags.action);
182 if (action == null) {
183 throw new ModelBuildException("Could not find WS-Addressing 1.0 Action element");
184 }
185 return action;
186 }
187
188 private Element getWSAddressingToElement() {
189 return getTag(SOAPTags.envelope, SOAPTags.header, WSATags.to);
190 }
191
192 private Element getLibertyFrameworkElement() {
193 final Element framework = getTag(SOAPTags.envelope, SOAPTags.header, LibertyTags.framework);
194 if (framework == null) {
195 throw new ModelBuildException("Could not find Liberty Framework element");
196 }
197 return framework;
198 }
199
200 private Element getTimestampElement() {
201 final Element timestamp = getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, WSUTags.timestamp);
202 if (timestamp == null) {
203 throw new ModelBuildException("Could not find Timestamp element");
204 }
205 return timestamp;
206 }
207
208 private Element getSecurityTokenReferenceElement() {
209 final Element securityTokenReference = getTag(SOAPTags.envelope, SOAPTags.header, WSSETags.security, WSSETags.securityTokenReference);
210 if (securityTokenReference == null) {
211 throw new ModelBuildException("Could not find SecurityTokenReference element");
212 }
213 return securityTokenReference;
214 }
215
216 private Element getBodyElement() {
217 final Element body = getTag(SOAPTags.envelope, SOAPTags.body);
218 if (body == null) {
219 throw new ModelBuildException("Could not find Body element");
220 }
221 return body;
222 }
223
224 }