View Javadoc

1   /*
2    * The MIT License
3    *
4    * Original work sponsored and donated by National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
5    *
6    * Copyright (C) 2011 National Board of e-Health (NSI), Denmark (http://www.nsi.dk)
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   *
26   * $HeadURL: https://svn.softwareborsen.dk/sosi/trunk/modules/seal/src/test/java/dk/sosi/seal/model/TestModel.java $
27   * $Id: TestModel.java 8697 2011-09-02 10:33:55Z chg@lakeside.dk $
28   */
29  package dk.sosi.seal.model;
30  
31  import dk.sosi.seal.SOSIFactory;
32  import dk.sosi.seal.model.constants.*;
33  import dk.sosi.seal.model.dombuilders.DOMBuilderException;
34  import dk.sosi.seal.modelbuilders.ModelBuildException;
35  import dk.sosi.seal.modelbuilders.ModelPrefixResolver;
36  import dk.sosi.seal.modelbuilders.SignatureInvalidModelBuildException;
37  import dk.sosi.seal.pki.Federation;
38  import dk.sosi.seal.pki.SOSITestFederation;
39  import dk.sosi.seal.pki.impl.HashMapCertificateCache;
40  import dk.sosi.seal.vault.CredentialVault;
41  import dk.sosi.seal.vault.CredentialVaultException;
42  import dk.sosi.seal.vault.CredentialVaultTestUtil;
43  import dk.sosi.seal.vault.EmptyCredentialVault;
44  import dk.sosi.seal.xml.XmlUtil;
45  import junit.framework.TestCase;
46  import org.apache.xpath.XPathAPI;
47  import org.w3c.dom.Document;
48  import org.w3c.dom.Element;
49  import org.w3c.dom.Node;
50  import org.w3c.dom.NodeList;
51  
52  import java.security.*;
53  import java.security.cert.X509Certificate;
54  import java.util.*;
55  
56  /**
57   * Test the model package
58   *
59   * @author Jan Riis
60   * @author $LastChangedBy: chg@lakeside.dk $
61   * @since 1.0
62   */
63  public class TestModel extends TestCase {
64  
65  	private Properties properties;
66  	private static long HOUR_IN_MILLIS = 60*60*1000;
67  
68  	protected void setUp() throws Exception {
69  		super.setUp();
70  		properties = SignatureUtil.setupCryptoProviderForJVM();
71  	}
72  
73  	public void testEmbeddedBodyElementRequest() throws Exception {
74  
75  		// Request
76  		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
77  		Request req = createRequestVOCES(factory, false, null, false);
78  		Document doc = XmlUtil.createEmptyDocument();
79  		Element bodyElement = doc.createElement("SomeXML");
80  		bodyElement.appendChild(doc.createElement("SomeNestedXML"));
81  		req.setBody(bodyElement);
82  
83  		req = cloneRequestBySerialization(factory, req);
84  		assertNull(XmlUtil.deepDiff(bodyElement, req.getBody()));
85  	}
86  
87  	public void testEmbeddedBodyElementReply() throws Exception {
88  
89  		// Reply
90  		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
91  		Reply reply = factory.createNewReply(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, "inResponseToID", "flowID", FlowStatusValues.FLOW_RUNNING);
92  		try {
93  			reply.getFaultCode();
94  			fail("Should not produce faultcode for non-error responses");
95  		} catch (Exception e) {
96  			// OK
97  		}
98  		try {
99  			reply.getFaultString();
100 			fail("Should not produce faultstring for non-error responses");
101 		} catch (Exception e) {
102 			// OK
103 		}
104 		Document doc = XmlUtil.createEmptyDocument();
105 		Element bodyElement = doc.createElement("SomeXML");
106 		bodyElement.appendChild(doc.createElement("SomeNestedXML"));
107 		reply.setBody(bodyElement);
108 		IDCard idcard = factory.createNewSystemIDCard(
109 				"test",
110 				new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
111 				AuthenticationLevel.VOCES_TRUSTED_SYSTEM, null, null,
112 				factory.getCredentialVault().getSystemCredentialPair().getCertificate(), null);
113 		reply.setIDCard(idcard);
114 
115 		reply = cloneReplyBySerialization(factory, reply);
116 		assertNull(XmlUtil.deepDiff(bodyElement, reply.getBody()));
117 	}
118 
119 	public void testEmbeddedBodyFaultElementReply() throws Exception {
120 
121 		String ERROR_MESSAGE = "The supplied signature is invalid";
122 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
123 
124 		// Reply
125 		Reply reply = factory.createNewErrorReply(DGWSConstants.VERSION_1_0_1, "test", null, FaultCodeValues.INVALID_SIGNATURE, ERROR_MESSAGE);
126 		assertTrue(reply.isFault());
127 		try {
128 			reply.getFlowStatus();
129 			fail("Should not produce flow status for error responses");
130 		} catch (Exception e) {
131 			// OK
132 		}
133 
134 		Reply reply1 = factory.createNewErrorReply(DGWSConstants.VERSION_1_0_1, "test", null, FaultCodeValues.INVALID_SIGNATURE, ERROR_MESSAGE);
135 		reply1.setMessageID(reply.getMessageID());
136 		assertEquals(reply, reply1);
137 
138 		reply1 = factory.createNewErrorReply(DGWSConstants.VERSION_1_0_1, XmlUtil.createNonce(), null, "OTHER FAILURE", ERROR_MESSAGE);
139 		assertFalse(reply.equals(reply1));
140 		reply1.setMessageID(reply.getMessageID());
141 		assertFalse(reply.equals(reply1));
142 		reply1.setRequestID(reply.getRequestID());
143 		assertFalse(reply.equals(reply1));
144 
145 		reply1 = factory.createNewErrorReply(DGWSConstants.VERSION_1_0_1, XmlUtil.createNonce(), null, FaultCodeValues.INVALID_SIGNATURE, "OTHER ERROR");
146 		assertFalse(reply.equals(reply1));
147 		reply1.setMessageID(reply.getMessageID());
148 		assertFalse(reply.equals(reply1));
149 		reply1.setRequestID(reply.getRequestID());
150 		assertFalse(reply.equals(reply1));
151 
152 		XmlUtil.createEmptyDocument();
153 		IDCard idcard = factory.createNewSystemIDCard(
154 				"test",
155 					new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
156 					AuthenticationLevel.VOCES_TRUSTED_SYSTEM, null, null,
157 					factory.getCredentialVault().getSystemCredentialPair().getCertificate(), null);
158 		try {
159 			reply.setIDCard(idcard);
160 			fail("ID card should not be supported in error replies");
161 		} catch(ModelException me) {
162 			// OK. ID-cards not supported in faults.
163 		}
164 
165 //		reply = cloneReplyBySerialization(factory, reply);
166 //
167 //		Element elmFault = (Element) reply.getBody();
168 //		assertNotNull(elmFault);
169 //
170 //		Element elmFaultCode = (Element) XPathAPI.selectSingleNode(elmFault, SOAPTags.FAULTCODE);
171 //		assertNotNull(elmFaultCode);
172 //
173 //		Element elmMedcomFaultCode = (Element) XPathAPI.selectSingleNode(elmFault, SOAPTags.DETAIL + '/' + MedComTags.FAULT_CODE);
174 //		assertNotNull(elmMedcomFaultCode);
175 //
176 //		Element elmFaultString = (Element) XPathAPI.selectSingleNode(elmFault, SOAPTags.FAULTSTRING);
177 //		assertNotNull(elmFaultString);
178 //
179 //		String strFaultCode = XmlUtil.getTextNodeValue(elmFaultCode);
180 //		String strMedcomFaultCode = XmlUtil.getTextNodeValue(elmMedcomFaultCode);
181 //		String strFaultString = XmlUtil.getTextNodeValue(elmFaultString);
182 //
183 //		assertTrue("Server".equals(strFaultCode));
184 //		assertTrue(FaultCodeValues.INVALID_SIGNATURE.equals(strMedcomFaultCode));
185 //		assertTrue(ERROR_MESSAGE.equals(strFaultString));
186 	}
187 
188 	public void testRequestRoundTripUserIDCard() throws Exception {
189 
190 		// Create a dummy flowId, must be base 64 encoded
191 		String flowId = XmlUtil.toBase64("flowId".getBytes());
192 
193 		// Create a SOSI SOAP Request with a self-signed IDCard
194 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
195 		Request request = createRequestVOCES(factory, false, flowId, true);
196 		Document doc = request.serialize2DOMDocument();
197 
198 		signatureTest(factory, request, doc);
199 	}
200 
201 	public void testRequestRoundTripSystemIDCard() throws Exception {
202 
203 		// Create a dummy flowId, must be base 64 encoded
204 		String flowId = XmlUtil.toBase64("flowId".getBytes());
205 
206 		// Create a SOSI SOAP Request with a self-signed IDCard
207 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
208 		Request request = createRequestVOCES(factory, false, flowId, false);
209 		Document doc = request.serialize2DOMDocument();
210 		signatureTest(factory, request, doc);
211 	}
212 
213 	public void testReplyRoundTripSystemIDCard() throws Exception {
214 
215 		// Create a dummy flowId, must be base 64 encoded
216 		String flowId = XmlUtil.toBase64("flowId".getBytes());
217 
218 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
219 
220 		Reply reply = factory.createNewReply(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, "inResponseToID", flowId, FlowStatusValues.FLOW_RUNNING);
221 
222 		Document doc = reply.serialize2DOMDocument();
223 		Element replyForBody = doc.createElement("TestReply");
224 		reply.setBody(replyForBody);
225 
226 		// Simulate that the message was written to a pipe and deserialized
227 		// again on the other side
228 		byte[] serialXml = XmlUtil.serializeXml2ByteArray(doc, false);
229 
230 		Reply newReply = factory.deserializeReply(new String(serialXml));
231 
232 		assertEquals(reply, newReply);
233 	}
234 
235 	/**
236 	 * Sign a document, and validate the signature
237 	 */
238 	public void testSignValidate() {
239 
240 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
241 		Request request = createRequestVOCES(factory, false, "testflow", true);
242 		Document doc = request.serialize2DOMDocument();
243 		Node elmSignature = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
244 
245 		if (!SignatureUtil.validate(elmSignature, factory.getFederation(), factory.getCredentialVault(),true))
246 			fail("Unable to validate signature");
247 	}
248 
249 	/**
250 	 * Check no signature is available on NoAuth security level
251 	 */
252 	public void testNoSignatureInNoAuthorisationLevel() {
253 
254 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
255 		Request request = createRequestNoAuth(factory, false, "testflow", true);
256 		Document doc = request.serialize2DOMDocument();
257 		Node elmSignature = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
258 		assertNull(elmSignature);
259 	}
260 
261 	/**
262 	 * Check EmptyCredentialVault exceptions
263 	 */
264 	public void testEmptyVaultExceptions() {
265 
266 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory(new EmptyCredentialVault());
267 		try {
268 			createRequestVOCES(factory, false, "testflow", true);
269 			fail("CredentialVaultException should be thrown");
270 		} catch (CredentialVaultException e) {
271 			// ok
272 		}
273 		try {
274 			createRequestMOCES(factory, false, "testflow");
275 			fail("CredentialVaultException should be thrown");
276 		} catch (CredentialVaultException e) {
277 			// ok
278 		}
279 	}
280 
281 	/**
282 	 * Test DOM caching and dirty flagging
283 	 */
284 	public void testIDCard() throws Exception {
285 
286 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
287 		Request request = createRequestVOCES(factory, true, "testflow", false);
288 		checkDuration(request.getIDCard());
289 		assertTrue(request.getIDCard().needsSignature);
290 		assertNull(request.getIDCard().lastDOMOperation);
291 
292 		// Check that two serializations are entirely equal (incl. ID card
293 		// serialization)
294 		Document doc1 = request.serialize2DOMDocument();
295 		Document doc2 = request.serialize2DOMDocument();
296 		assertNull(XmlUtil.deepDiff(doc1, doc2));
297 
298 		// Check implicite signing
299 		request = createRequestVOCES(factory, true, "testflow", false);
300 		checkDuration(request.getIDCard());
301 		doc1 = XmlUtil.createEmptyDocument();
302 		request.getIDCard().serialize2DOMDocument(factory, doc1);
303 		assertNull(request.getIDCard().getSignedByCertificate());
304 		assertTrue(request.getIDCard().needsSignature); // IDCard serialization
305 		// does not create
306 		// implicite signature
307 		doc1 = request.serialize2DOMDocument();
308 		assertNotNull(request.getIDCard().getSignedByCertificate());
309 		assertEquals(IDCard.SIGNED, request.getIDCard().lastDOMOperation); // Message
310 		// serialization
311 		// should
312 		// implicitly
313 		// sign
314 		// VOCES
315 		// IDCard
316 
317 		// Check IDCard node import
318 		request = createRequestVOCES(factory, true, "testflow", false);
319 		checkDuration(request.getIDCard());
320 		doc1 = request.serialize2DOMDocument();
321 		doc2 = request.serialize2DOMDocument();
322 		assertFalse(request.getIDCard().needsSignature);
323 		assertEquals(IDCard.RE_ASSIGNED, request.getIDCard().lastDOMOperation);
324 
325 		// Check MOCES userIDCard
326 		Request mocesRequest = createRequestMOCES(factory, false, "testflow");
327 		checkDuration(mocesRequest.getIDCard());
328 		assertTrue(mocesRequest.getIDCard().needsSignature);
329 		assertNull(mocesRequest.getIDCard().lastDOMOperation);
330 		mocesRequest.serialize2DOMDocument();
331 		assertTrue(mocesRequest.getIDCard().needsSignature);
332 		assertEquals(IDCard.CREATED, mocesRequest.getIDCard().lastDOMOperation);
333 	}
334 
335 	private void checkDuration(IDCard card) {
336 		int MAX_IDCARD_LIFE_IN_MS = 24 * 60 * 60 * 1000;
337 		long diff = card.getExpiryDate().getTime() - card.getCreatedDate().getTime();
338 		assertTrue(diff <= MAX_IDCARD_LIFE_IN_MS);
339 	}
340 
341 	public void testBadIDCards() throws Exception {
342 
343 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
344 		try {
345 			factory.createNewUserIDCard(
346 					"testITSystem",
347 					new UserInfo("012345678", "Jan", "Riis", "jan<at>lakeside.dk", "testOccupation", null, "2101"),
348 					new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
349 					AuthenticationLevel.VOCES_TRUSTED_SYSTEM,
350 					null,
351 					null,
352 					factory	.getCredentialVault().getSystemCredentialPair().getCertificate(),
353 					null
354 			);
355 			fail("Null role should fail");
356 		} catch (ModelException me) {
357 			// OK
358 		}
359 
360 		try {
361 			factory.createNewUserIDCard(
362 					"testITSystem",
363 					new UserInfo("012345678", "Jan", "Riis", "jan<at>lakeside.dk", "testOccupation", "nurse", "2101"),
364 					new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
365 					null,
366 					null,
367 					null,
368 					factory	.getCredentialVault().getSystemCredentialPair().getCertificate(),
369 					null
370 			);
371 			fail("Null authenticationlevel should fail");
372 		} catch (ModelException me) {
373 			// OK
374 		}
375 
376 		try {
377 			factory.createNewUserIDCard("itSystemName", null, new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"), AuthenticationLevel.NO_AUTHENTICATION,
378 					null, null, null, null);
379 			fail("Null userinfo should fail");
380 		} catch (ModelException me) {
381 			// OK
382 		}
383 	}
384 
385 	// build message, remove saml attribute, validate validator
386 	public void testMessageTypesForValidAttributes() {
387 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
388 
389 		// IDCardData
390 		checkMissingSamlAttribute(factory, "sosi:IDCardID");
391 		checkMissingSamlAttribute(factory, "sosi:IDCardVersion");
392 		checkMissingSamlAttribute(factory, "sosi:IDCardType");
393 		checkMissingSamlAttribute(factory, "sosi:AuthenticationLevel");
394 //		checkMissingSamlAttribute(factory, "sosi:OCESCertHash");
395 
396 		//SystemInfo
397 		checkMissingSamlAttribute(factory, "medcom:ITSystemName");
398 		checkMissingSamlAttribute(factory, "medcom:CareProviderID");
399 		checkMissingSamlAttribute(factory, "medcom:CareProviderName");
400 
401 		//UserInfo
402 		checkMissingSamlAttribute(factory, "medcom:UserCivilRegistrationNumber");
403 		checkMissingSamlAttribute(factory, "medcom:UserGivenName");
404 		checkMissingSamlAttribute(factory, "medcom:UserSurName");
405 	}
406 
407 	private void checkMissingSamlAttribute(SOSIFactory factory, String samlAtt) {
408 		try {
409 			// securitytokenrequest
410 			SecurityTokenRequest request = factory.createNewSecurityTokenRequest();
411 			SecurityTokenResponse message = factory.createNewSecurityTokenResponse(request);
412 			UserIDCard idCardWithCpr = createNewUserIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION, null, "0123456789");
413 			message.setIDCard(idCardWithCpr);
414 
415 			Document dom = XmlUtil.createEmptyDocument();
416 			message.serialize2DOMDocument(dom);
417 			removeSAMLAttribute(dom, samlAtt);
418 			String xml = XmlUtil.node2String(dom, false, true);
419 //			System.out.println(xml);
420 			factory.deserializeSecurityTokenResponse(xml);
421 			fail("Should fail on "+samlAtt+" missing..");
422 		} catch (ModelException e) {
423 			// success
424 //			System.out.println(samlAtt+": "+e.getMessage());
425 		} catch (ModelBuildException e) {
426 			// IDCardVersion parsing
427 			// success
428 		} catch (NumberFormatException e) {
429 			//AuthLevel parsing
430 			// success
431 		}
432 	}
433 
434 	private void removeSAMLAttribute(Document dom, String samlAtt) {
435 		NodeList attributes = dom.getElementsByTagNameNS(NameSpaces.SAML2ASSERTION_SCHEMA, "Attribute");
436 
437 		for (int i = 0; i < attributes.getLength(); i++) {
438             Node elmAttr = attributes.item(i);
439 			if(samlAtt.equals(elmAttr.getAttributes().item(0).getNodeValue())) {
440             	elmAttr.getParentNode().removeChild(elmAttr);
441                 break;
442             }
443 		}
444 	}
445 
446 	public void testRequestsAndResponsesForValidCPR() {
447 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
448 		// userid cards
449 		// securitytokenrequest
450 		SecurityTokenRequest streq = factory.createNewSecurityTokenRequest();
451 		checkCpr(factory, streq, true);
452 
453 		// securitytokenresponse
454 		SecurityTokenRequest tokenRequest = factory.createNewSecurityTokenRequest();
455 		SecurityTokenResponse stresp = factory.createNewSecurityTokenResponse(tokenRequest);
456 		checkCpr(factory, stresp, false);
457 
458 		// request
459 		Request req = factory.createNewRequest(false, "testflow");
460 		checkCpr(factory, req, false);
461 
462 		// response
463 		Reply reply = factory.createNewReply(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, "inResponseToID", "flowID", FlowStatusValues.FLOW_RUNNING);
464 		checkCpr(factory, reply, false);
465 	}
466 
467 	private void checkCpr(SOSIFactory factory, Message message, boolean emptyCprAllowed) {
468 		UserIDCard idCardWithCpr = createNewUserIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION, null, "0123456789");
469 		message.setIDCard(idCardWithCpr);
470 		deserializeMessage(factory, message);
471 		try {
472 			UserIDCard idCardWithoutCpr = createNewUserIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION, null, null);
473 			message.setIDCard(idCardWithoutCpr);
474 			deserializeMessage(factory, message);
475 			if(!emptyCprAllowed)
476 				fail("Should throw ModelException");
477 		} catch (ModelException e) {}
478 	}
479 
480 	private void deserializeMessage(SOSIFactory factory, Message message) {
481 		Document dom = message.serialize2DOMDocument();
482 		String xml = XmlUtil.node2String(dom, false, true);
483 		if(message instanceof Request) factory.deserializeRequest(xml);
484 		else if(message instanceof Reply) factory.deserializeReply(xml);
485 		else if(message instanceof SecurityTokenRequest) factory.deserializeSecurityTokenRequest(xml);
486 		else if(message instanceof SecurityTokenResponse) factory.deserializeSecurityTokenResponse(xml);
487 	}
488 
489 	/**
490 	 * Test serialization into more or less prepared DOM documents.
491 	 */
492 	public void testPreparedDOMDocument() throws Exception {
493 
494 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
495 		Request req = createRequestVOCES(factory, true, "1234", true);
496 		Document fromEmptyDoc = req.serialize2DOMDocument();
497 
498 		Document fromAnotherEmptyDoc = req.serialize2DOMDocument();
499 
500 		assertNull(XmlUtil.deepDiff(fromEmptyDoc, fromAnotherEmptyDoc));
501 
502 		Document templateDoc = XmlUtil.createEmptyDocument();
503 		Element root = templateDoc.createElementNS(NameSpaces.SOAP_SCHEMA, SOAPTags.ENVELOPE_PREFIXED);
504 		String checkAttribute = "preparedtest";
505 		String checkValue = "jriTest";
506 		root.setAttribute(checkAttribute, checkValue);
507 		templateDoc.appendChild(root);
508 
509 		Document docRoot = (Document) templateDoc.cloneNode(true);
510 		req.serialize2DOMDocument(docRoot);
511 		assertTrue("soap:Envelope element was not reused!", docRoot.getDocumentElement().getChildNodes().getLength() > 0);
512 		assertEquals("soap:Envelope element was replaced!", docRoot.getDocumentElement().getAttribute(checkAttribute), checkValue);
513 
514 		// Test that already added attributes are left alone
515 		docRoot = (Document) templateDoc.cloneNode(true);
516 		Map<String, String> nameSpaces = new HashMap<String, String>(NameSpaces.SOSI_NAMESPACES); // Shallow
517 		// copy
518 		// Change one of the namespaces and check that it is left alone
519 		String someKey = nameSpaces.keySet().iterator().next();
520 		nameSpaces.put(someKey, "test");
521 		for (Iterator<String> iter = nameSpaces.keySet().iterator(); iter.hasNext();) {
522 			String key = iter.next();
523 			docRoot.getDocumentElement().setAttributeNS(NameSpaces.XMLNS_SCHEMA, NameSpaces.NS_XMLNS + ":" + key, nameSpaces.get(key));
524 		}
525 		req.serialize2DOMDocument(docRoot);
526 		assertEquals(docRoot.getDocumentElement().getAttribute(NameSpaces.NS_XMLNS + ":" + someKey), "test");
527 
528 		// Test that prepared soap:Header is reused
529 		Element header = templateDoc.createElementNS(NameSpaces.SOAP_SCHEMA, SOAPTags.HEADER_PREFIXED);
530 		header.setAttribute(checkAttribute, checkValue);
531 		root.appendChild(header);
532 		Document docHeader = (Document) templateDoc.cloneNode(true);
533 		req.serialize2DOMDocument(docHeader);
534 		assertTrue("soap:Header element was not reused!", docHeader.getDocumentElement().getFirstChild().getChildNodes().getLength() > 0);
535 		assertEquals("soap:Header element was replaced!", checkValue, ((Element) docHeader.getDocumentElement().getFirstChild())
536 				.getAttribute(checkAttribute));
537 
538 		// Check that header elements are copied
539 		Element headerElement = templateDoc.createElementNS(NameSpaces.WSSE_SCHEMA, NameSpaces.NS_WSSE + ":Security");
540 		header.appendChild(headerElement);
541 		docHeader = (Document) templateDoc.cloneNode(true);
542 		req.serialize2DOMDocument(docHeader);
543 		assertTrue("soap:Header child element was not copied!", docHeader.getDocumentElement().getFirstChild().getChildNodes().item(0)
544 				.getChildNodes().getLength() > 0);
545 
546 		// Test that prepared soap:Body is reused
547 		Element body = templateDoc.createElementNS(NameSpaces.SOAP_SCHEMA, SOAPTags.BODY_PREFIXED);
548 		body.setAttribute(checkAttribute, checkValue);
549 		root.appendChild(body);
550 		Document docBody = (Document) templateDoc.cloneNode(true);
551 		req.serialize2DOMDocument(docBody);
552 		assertTrue("soap:Header element was not reused!", docBody.getDocumentElement().getFirstChild().getChildNodes().getLength() > 0);
553 		assertEquals("soap:Body element was replaced!", checkValue, ((Element) docBody.getDocumentElement().getFirstChild())
554 				.getAttribute(checkAttribute));
555 
556 		// Test that multiple soap:Header or multiple soap:Body elements
557 		// triggers an exception
558 		Document docTemp = (Document) templateDoc.cloneNode(true);
559 		Element header2 = (Element) docTemp.importNode(header, true);
560 		docTemp.getDocumentElement().appendChild(header2);
561 		try {
562 			req.serialize2DOMDocument(docTemp);
563 			fail("Multiple soap:Headers did not trigger a DOMBuilderException!");
564 		} catch (DOMBuilderException dbe) {
565 			// OK!
566 		}
567 
568         //TODO add namespaces to xml so body can be found
569 		docTemp = (Document) templateDoc.cloneNode(true);
570 		Element body2 = (Element) docTemp.importNode(body, true);
571 		docTemp.getDocumentElement().appendChild(body2);
572 		try {
573 			req.serialize2DOMDocument(docTemp);
574 			fail("Multiple soap:Body did not trigger a DOMBuilderException!");
575 		} catch (DOMBuilderException dbe) {
576 			// OK!
577 		}
578 	}
579 
580 	public void testSerializationEquality() throws Exception {
581 
582 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
583 
584 		// Now try with an embedded ID card
585 		Request request = createRequestVOCES(factory, true, "testflow", false);
586 		Document reqDom = request.serialize2DOMDocument();
587 		assertNull(XmlUtil.deepDiff(reqDom, reqDom));
588 		Document doc = XmlUtil.readXml(properties, XmlUtil.node2String(reqDom, false, true), false);
589 		Node deepDiff = XmlUtil.deepDiff(reqDom, doc);
590 		assertNull(deepDiff);
591 	}
592 
593 	/**
594 	 * Replace an IDCard and check that the signature still validates.
595 	 */
596 	public void testIDCardReplacement() {
597 
598 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
599 		Request req1 = createRequestVOCES(factory, false, "testflow", true);
600 
601 		// Validate the ID card signature
602 		Document doc1 = req1.serialize2DOMDocument();
603 		Node elmSignature = doc1.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
604 
605 		if (!SignatureUtil.validate(elmSignature, factory.getFederation(), factory.getCredentialVault(),true))
606 			fail("Unable to validate signature 1");
607 
608 		// Create new request on a new document, replace the ID-card and recheck
609 		// the signature
610 		Document doc2 = XmlUtil.createEmptyDocument();
611 		Request req2 = factory.createNewRequest(true, "1234");
612 		req2.setIDCard(req1.getIDCard());
613 		req2.setBody(doc2.createElement("test"));
614 		req2.serialize2DOMDocument(doc2);
615 		elmSignature = doc2.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
616 
617 		if (!SignatureUtil.validate(elmSignature, factory.getFederation(), factory.getCredentialVault(),true))
618 			fail("Unable to validate signature after replacement");
619 
620 	}
621 
622 	public void testIDCardSignatureAfterSerialization() throws Exception {
623 
624 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
625 		Request request = createRequestVOCES(factory, false, "testflow", true);
626 		assertTrue(request.getIDCard().needsSignature);
627 		request.serialize2DOMDocument();
628 		assertFalse(request.getIDCard().needsSignature);
629 
630 		Document newDoc = request.serialize2DOMDocument();
631 		request = factory.deserializeRequest(XmlUtil.node2String(newDoc, false, true));
632 		assertFalse(request.getIDCard().needsSignature);
633 	}
634 
635 	public void testMOCESSignatureNeg() throws Exception {
636 
637 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
638 		Request request = createRequestMOCES(factory, false, "testflow");
639 		Document doc = request.serialize2DOMDocument();
640 		assertTrue(request.getIDCard().needsSignature);
641 
642 		// Trigger generation of the SignedInfo element
643 		request.getIDCard().getBytesForSigning(doc);
644 
645 		// Check negative case first
646 		try {
647 			request.getIDCard().injectSignature("bogus signature", factory.getCredentialVault().getSystemCredentialPair().getCertificate());
648 			fail("injectSignature() should fail on invalid signature");
649 		} catch (ModelException me) {
650 			// OK!
651 		}
652 	}
653 
654 	public void testSignedInfoDigests() throws Exception {
655 
656 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
657 		Request req = createRequestMOCES(factory, false, "testflow");
658 		Document doc = req.serialize2DOMDocument();
659 
660 		// Check that there is no digest in the XML
661 		NodeList digests = doc.getElementsByTagNameNS("ds","DigestValue");
662 		assertTrue(digests.getLength() == 0);
663 
664 		// Calculate the digest value from the XML
665 		String siStr = new String(req.getIDCard().getBytesForSigning(doc));
666 		String siDigest = siStr.split("\\<ds:DigestValue")[1].split("\\>")[1].split("\\<")[0];
667 
668 		// Provoke a VOCES signature on the IDCard
669 		req.getIDCard().needsSignature = true;
670 		req.getIDCard().domElement = null;
671 		Document doc1 = req.serialize2DOMDocument();
672 		req.getIDCard().sign(doc1, factory.getCredentialVault());
673 
674 		// Test equality of digests
675 		digests = doc1.getElementsByTagName("ds:DigestValue");
676 		assertTrue(digests.getLength() == 1);
677 		assertEquals(siDigest, XmlUtil.getTextNodeValue(digests.item(0)));
678 	}
679 
680 	public void testMOCESSignature() throws Exception {
681 
682 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
683 		Request req = createRequestMOCES(factory, false, "testflow");
684 		Document doc = req.serialize2DOMDocument();
685 
686 		// Check that there is still no digest in the XML
687 		NodeList digests = doc.getElementsByTagNameNS(NameSpaces.NS_DS, "DigestValue");
688 		assertTrue(digests.getLength() == 0);
689 
690 		// Calculate and inject signature
691 		String signature = createSignature(factory, req, doc);
692 		req.getIDCard().injectSignature(signature, factory.getCredentialVault().getSystemCredentialPair().getCertificate());
693 
694 		// Check the signature
695 		Element signatureParentElement = (Element) XmlUtil.getElementByIdExtended(doc, IDValues.IDCARD);
696 		NodeList signatures = signatureParentElement.getElementsByTagNameNS(NameSpaces.DSIG_SCHEMA, "Signature");
697 		if (signatures.getLength() != 1) {
698 			throw new ModelException("Expected 1 but found " + signatures.getLength() + " SignatureValue elements");
699 		}
700 		assertTrue(signatures.getLength() == 1);
701 		assertTrue(SignatureUtil.validate(signatures.item(0), factory.getFederation(), factory.getCredentialVault(),true));
702 
703 		// For namespaces already declared in the root element:
704 		// Re-declaring them or removing extra declarations should not break the signature
705 		Element samlAssertion = (Element) XPathAPI.selectSingleNode(doc, "//" + SAMLTags.ASSERTION_PREFIXED);
706 		samlAssertion.removeAttribute("xmlns:saml");
707 		samlAssertion.removeAttribute("xmlns:ds");
708 		samlAssertion.setAttributeNS(NameSpaces.XMLNS_SCHEMA, "xmlns:medcom", NameSpaces.MEDCOM_SCHEMA);
709 		((Element) samlAssertion.getFirstChild()).setAttributeNS(NameSpaces.XMLNS_SCHEMA, "xmlns:ds", NameSpaces.DSIG_SCHEMA);
710 		assertTrue(SignatureUtil.validate(signatures.item(0), factory.getFederation(), factory.getCredentialVault(), true));
711 
712 		// Try to tamper the signed IDCard
713 		Node node = XPathAPI.selectSingleNode(doc, "//saml:Attribute[@Name='medcom:UserAuthorizationCode']/saml:AttributeValue");
714 		assertNotNull(node);
715 		node.getFirstChild().setNodeValue("dummy");
716 		assertFalse(SignatureUtil.validate(signatures.item(0), factory.getFederation(), factory.getCredentialVault(),true));
717 
718 	}
719 
720 	public void testInvalidInjectSignature() throws Exception {
721 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
722 		Request req = createRequestMOCES(factory, false, "testflow");
723 		Document doc = req.serialize2DOMDocument();
724 
725 		String signature = createSignature(factory, req, doc);
726 		try {
727 			//try to inject the signature together with a different certificate that the one used to sign
728 			req.getIDCard().injectSignature(signature, CredentialVaultTestUtil.getVocesCredentialVault().getSystemCredentialPair().getCertificate());
729 			fail("Injecting signature together with a different certificate that the one used to sign should fail");
730 		} catch (ModelException e) {
731 			// Ok
732 		}
733 
734 		try {
735 			req.getIDCard().injectSignature(signature, null);
736 			fail("Injecting signature without corresponding certificate should fail");
737 		} catch (ModelException e) {
738 			// Ok
739 		}
740 
741 	}
742 
743 	public void testCopyMocesIDCard() throws Exception {
744 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
745 		Request req1 = createRequestMOCES(factory, false, "testflow");
746         UserIDCard unsignedIdCard = (UserIDCard) req1.getIDCard();
747         unsignedIdCard.sign(req1.serialize2DOMDocument(), factory.getCredentialVault());
748 		assertNotNull(unsignedIdCard.getSignedByCertificate());
749 
750 		Request req2 = createRequestMOCES(factory, false, "testflow");
751         UserIDCard signedIdCard = (UserIDCard) factory.copyToVOCESSignedIDCard(unsignedIdCard);
752         req2.setIDCard(signedIdCard);
753         assertEquals(signedIdCard, req2.getIDCard());
754 
755         // Check that req2 is VOCES signed, but has authentication level 4
756         assertEquals(AuthenticationLevel.MOCES_TRUSTED_USER, signedIdCard.getAuthenticationLevel());
757         assertFalse(signedIdCard.needsSignature);
758         assertEquals(IDCard.SIGNED, signedIdCard.lastDOMOperation);
759         assertEquals(unsignedIdCard.getUserInfo().getCPR(), signedIdCard.getUserInfo().getCPR());
760 	}
761 
762     public void testCopyMocesIDCardOverwriteCpr() {
763         SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
764         Request req1 = createRequestMOCES(factory, false, "testflow");
765         UserIDCard unsignedIdCard = (UserIDCard) req1.getIDCard();
766         unsignedIdCard.sign(req1.serialize2DOMDocument(), factory.getCredentialVault());
767         assertNotNull(unsignedIdCard.getSignedByCertificate());
768 
769         String newCpr = "1111111118";
770 
771         Request req2 = createRequestMOCES(factory, false, "testflow");
772         final UserInfo newUserInfo = new UserInfo(unsignedIdCard.getUserInfo(), newCpr);
773         UserIDCard signedIdCard = (UserIDCard) factory.copyToVOCESSignedIdCard(unsignedIdCard, newUserInfo);
774         req2.setIDCard(signedIdCard);
775         assertEquals(signedIdCard, req2.getIDCard());
776 
777         // Check that req2 is VOCES signed, but has authentication level 4
778         assertEquals(AuthenticationLevel.MOCES_TRUSTED_USER, signedIdCard.getAuthenticationLevel());
779         assertFalse(signedIdCard.needsSignature);
780         assertEquals(IDCard.SIGNED, signedIdCard.lastDOMOperation);
781         assertEquals(newCpr, signedIdCard.getUserInfo().getCPR());
782     }
783 
784     public void testCopyMocesIDCardOverwriteUserInfo() {
785         SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
786         Request req1 = createRequestMOCES(factory, false, "testflow");
787         UserIDCard unsignedIdCard = (UserIDCard) req1.getIDCard();
788         unsignedIdCard.sign(req1.serialize2DOMDocument(), factory.getCredentialVault());
789         assertNotNull(unsignedIdCard.getSignedByCertificate());
790 
791         String newCpr = "1111111118";
792 
793         Request req2 = createRequestMOCES(factory, false, "testflow");
794         UserInfo newUserInfo = new UserInfo(unsignedIdCard.getUserInfo(), newCpr);
795         UserIDCard signedIdCard = (UserIDCard) factory.copyToVOCESSignedIdCard(unsignedIdCard, newUserInfo);
796         req2.setIDCard(signedIdCard);
797         assertEquals(signedIdCard, req2.getIDCard());
798 
799         // Check that req2 is VOCES signed, but has authentication level 4
800         assertEquals(AuthenticationLevel.MOCES_TRUSTED_USER, signedIdCard.getAuthenticationLevel());
801         assertFalse(signedIdCard.needsSignature);
802         assertEquals(IDCard.SIGNED, signedIdCard.lastDOMOperation);
803         assertEquals(newCpr, signedIdCard.getUserInfo().getCPR());
804     }
805 
806 	public void testCopyExternallySignedIDCard() throws Exception {
807 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
808 		SecurityTokenRequest req1 = createSecurityTokenRequest(factory, true, false, AuthenticationLevel.MOCES_TRUSTED_USER, "2512484916");
809 		Document doc = req1.serialize2DOMDocument();
810 		String signature = createSignature(factory, req1, doc);
811 		req1.getIDCard().injectSignature(signature, factory.getCredentialVault().getSystemCredentialPair().getCertificate());
812 
813 		assertNotNull(req1.getIDCard().getSignedByCertificate());
814 		assertNull(req1.getIDCard().getCertHash());
815 
816 		Request req2 = createRequestMOCES(factory, false, "testflow");
817 		req2.setIDCard(factory.copyToVOCESSignedIDCard(req1.getIDCard()));
818 
819 		assertEquals(req1.getIDCard().getSignedByCertificate(), req2.getIDCard().getSignedByCertificate());
820 		assertNotNull(req2.getIDCard().getCertHash());
821 	}
822 
823 	public void testCopyMocesIDCardWithNewCpr() throws Exception {
824 
825 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
826 		SecurityTokenRequest req1 = factory.createNewSecurityTokenRequest();
827 		UserIDCard idCard = createNewUserIdCard(factory, AuthenticationLevel.MOCES_TRUSTED_USER,
828 				factory.getCredentialVault().getSystemCredentialPair().getCertificate(), "");
829 		req1.setIDCard(idCard);
830 
831 		Document doc = req1.serialize2DOMDocument();
832 		req1.getIDCard().sign(doc, factory.getCredentialVault());
833 
834 		Request req2 = createRequestMOCES(factory, false, "testflow");
835         final UserInfo newUserInfo = new UserInfo(((UserIDCard) req1.getIDCard()).getUserInfo(), "0123456789");
836 		req2.setIDCard(factory.copyToVOCESSignedIdCard((UserIDCard) req1.getIDCard(), newUserInfo));
837 
838 		// Check that req2 has cpr
839 		assertEquals("0123456789", ((UserIDCard)req2.getIDCard()).getUserInfo().getCPR());
840 	}
841 
842 	public void testCopyVocesIDCard() throws Exception {
843 
844 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
845 		Request req1 = createRequestVOCES(factory, false, "testflow", false);
846 		Document doc = req1.serialize2DOMDocument();
847 		req1.getIDCard().sign(doc, factory.getCredentialVault());
848 
849 		Request req2 = createRequestMOCES(factory, false, "testflow");
850 
851         req2.setIDCard(factory.copyToVOCESSignedIDCard(req1.getIDCard()));
852 
853 		// Check that req2 is VOCES signed, but has authentication level 3
854 		assertEquals(AuthenticationLevel.VOCES_TRUSTED_SYSTEM, req2.getIDCard().getAuthenticationLevel());
855 		assertFalse(req2.getIDCard().needsSignature);
856 		assertEquals(IDCard.SIGNED, req2.getIDCard().lastDOMOperation);
857 	}
858 
859 	public void testCopyVocesIDCardOnSTS() throws Exception {
860 
861 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
862 		// without certificate
863 		SecurityTokenRequest req1 = createSecurityTokenRequestVOCES(factory, false, false);
864 		Document doc = req1.serialize2DOMDocument();
865 		assertTrue(XmlUtil.node2String(doc, false, true).indexOf("OCESCertHash") == -1);
866 		req1.getIDCard().sign(doc, factory.getCredentialVault());
867 		assertTrue(XmlUtil.node2String(doc, false, true).indexOf("OCESCertHash") == -1);
868 
869 		SecurityTokenResponse resp1 = factory.createNewSecurityTokenResponse(req1);
870 		// the copyToVoces should add certhash
871 		resp1.setIDCard(factory.copyToVOCESSignedIDCard(req1.getIDCard()));
872 
873 		assertNotNull(resp1.getIDCard().getCertHash());
874 		// Check that resp1 is VOCES signed, but has authentication level 3
875 		assertEquals(AuthenticationLevel.VOCES_TRUSTED_SYSTEM, resp1.getIDCard().getAuthenticationLevel());
876 		assertFalse(resp1.getIDCard().needsSignature);
877 		assertEquals(IDCard.SIGNED, resp1.getIDCard().lastDOMOperation);
878 		assertTrue(XmlUtil.node2String(resp1.serialize2DOMDocument(), false, true).indexOf("OCESCertHash") != -1);
879 	}
880 
881 	public void testMOCESAuthenticationLevel() throws Exception {
882 
883 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
884 		Request req = createRequestMOCES(factory, false, "testflow");
885 		assertEquals(AuthenticationLevel.MOCES_TRUSTED_USER, req.getIDCard().getAuthenticationLevel());
886 
887 		Document doc = req.serialize2DOMDocument();
888 		String xml = XmlUtil.node2String(doc, false, true);
889 
890 		// Deserializing an ID card with no signature should result in an
891 		// exception
892 		try {
893 			factory.deserializeRequest(xml);
894 			fail("Deserializing an ID card with no signature should result in an exception");
895 		} catch (SignatureInvalidModelBuildException simbe) {
896 			assertEquals(req.getFlowID(), simbe.getFlowID());
897 			assertEquals(req.getMessageID(), simbe.getMessageID());
898 		}
899 
900 		// Calculate and inject signature
901 		String signature = createSignature(factory, req, doc);
902 		req.getIDCard().injectSignature(signature, factory.getCredentialVault().getSystemCredentialPair().getCertificate());
903 		doc = req.serialize2DOMDocument();
904 		xml = XmlUtil.node2String(doc, false, true);
905 		req = factory.deserializeRequest(xml);
906 		assertEquals(AuthenticationLevel.MOCES_TRUSTED_USER, req.getIDCard().getAuthenticationLevel());
907 	}
908 
909 	public void testVOCESAuthenticationLevelUser() throws Exception {
910 
911 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
912 		Request req = createRequestVOCES(factory, true, "testflow", true);
913 		Document doc = req.serialize2DOMDocument();
914 		String xml = XmlUtil.node2String(doc, false, true);
915 		req = factory.deserializeRequest(xml);
916 		assertEquals(AuthenticationLevel.VOCES_TRUSTED_SYSTEM, req.getIDCard().getAuthenticationLevel());
917 	}
918 
919 	public void testVOCESAuthenticationLevelSystem() throws Exception {
920 
921 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
922 		Request req = createRequestVOCES(factory, false, "testflow", false);
923 		req = cloneRequestBySerialization(factory, req);
924 		assertEquals(AuthenticationLevel.VOCES_TRUSTED_SYSTEM, req.getIDCard().getAuthenticationLevel());
925 	}
926 
927 	public void testNoAuthenticationLevelSystem() throws Exception {
928 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
929 		Request req = createRequestNoAuth(factory, false, "testflow", false);
930 		req = cloneRequestBySerialization(factory, req);
931 		assertEquals(AuthenticationLevel.NO_AUTHENTICATION, req.getIDCard().getAuthenticationLevel());
932 	}
933 
934 	public void testNoAuthenticationLevelUser() throws Exception {
935 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
936 		Request req = createRequestNoAuth(factory, false, "testflow", true);
937 		req = cloneRequestBySerialization(factory, req);
938 		assertEquals(AuthenticationLevel.NO_AUTHENTICATION, req.getIDCard().getAuthenticationLevel());
939 	}
940 
941 	public void testNoAuthenticationLevelSystemWithEmptyVault() throws Exception {
942 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory(new EmptyCredentialVault());
943 		Request req = createRequestNoAuth(factory, false, "testflow", false);
944 		req = cloneRequestBySerialization(factory, req);
945 		assertEquals(AuthenticationLevel.NO_AUTHENTICATION, req.getIDCard().getAuthenticationLevel());
946 	}
947 
948 	public void testNoAuthenticationLevelUserWithEmptyVault() throws Exception {
949 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory(new EmptyCredentialVault());
950 		Request req = createRequestNoAuth(factory, false, "testflow", true);
951 		req = cloneRequestBySerialization(factory, req);
952 		assertEquals(AuthenticationLevel.NO_AUTHENTICATION, req.getIDCard().getAuthenticationLevel());
953 	}
954 
955 	public void testAuthenticationLevelNeg() throws Exception {
956 
957 		try {
958 			AuthenticationLevel.getEnumeratedValue(10);
959 			fail("getEnumeratedValue should fail on invalid level");
960 		} catch (ModelException me) {
961 			// OK
962 		}
963 	}
964 
965 	public void testMessageEquals() throws Exception {
966 
967 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
968 		Request req = createRequestVOCES(factory, false, "testflow", false);
969 		checkBasicEquals(req);
970 
971 		Request reqClone = cloneRequestBySerialization(factory, req);
972 		assertEquals(req, reqClone);
973 
974 		reqClone.setCreationDate(new Date(System.currentTimeMillis() + 2000));
975 		assertFalse(req.equals(reqClone));
976 
977 		Request reqTemp = createRequestVOCES(factory, false, "testflow", false);
978 		reqClone = cloneRequestBySerialization(factory, req);
979 		assertEquals(req, reqClone);
980 		reqClone.setIDCard(reqTemp.getIDCard());
981 		assertFalse(req.equals(reqClone));
982 
983 		reqClone = cloneRequestBySerialization(factory, req);
984 		assertEquals(req, reqClone);
985 		reqClone.setFlowID("bogusFlow");
986 		assertFalse(req.equals(reqClone));
987 
988 		CareProvider careProvider = new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "orgCVR", "orgName");
989 		IDCard idCard = factory.createNewSystemIDCard("SOSITEST", careProvider, AuthenticationLevel.VOCES_TRUSTED_SYSTEM, null, null,
990 				factory.getCredentialVault().getSystemCredentialPair().getCertificate(), null);
991 
992 		SecurityTokenRequest securityTokenRequest = factory.createNewSecurityTokenRequest();
993 		securityTokenRequest.setIDCard(idCard);
994 		SecurityTokenRequest securityTokenRequestClone = cloneSecurityTokenRequestBySerialization(factory, securityTokenRequest);
995 		assertEquals(securityTokenRequest, securityTokenRequestClone);
996 
997 		SecurityTokenResponse securityTokenResponse = factory.createNewSecurityTokenResponse(securityTokenRequest);
998 		securityTokenResponse.setIDCard(idCard);
999 		SecurityTokenResponse securityTokenResponseClone = cloneSecurityTokenResponseBySerialization(factory, securityTokenResponse);
1000 		assertEquals(securityTokenResponse, securityTokenResponseClone);
1001 
1002 	}
1003 
1004 	public void testReplyEquals() throws Exception {
1005 
1006 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1007 		Reply reply = factory.createNewReply(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, "inResponseToID", "flowID", FlowStatusValues.FLOW_RUNNING);
1008 		checkBasicEquals(reply);
1009 
1010 		// Test requestID
1011 		Reply clonedReply = cloneReplyBySerialization(factory, reply);
1012 		assertEquals(reply, clonedReply);
1013 		clonedReply.setRequestID("bogus");
1014 		assertFalse(reply.equals(clonedReply));
1015 
1016 		// Test flow status
1017 		clonedReply = cloneReplyBySerialization(factory, reply);
1018 		clonedReply.setFlowStatus("bogus");
1019 		assertFalse(reply.equals(clonedReply));
1020 	}
1021 
1022 	public void testIDCardEquals() throws Exception {
1023 
1024 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1025 		Request req = createRequestVOCES(factory, false, "testflow", false);
1026 		IDCard idcard = req.getIDCard();
1027 		checkBasicEquals(idcard);
1028 
1029 		Document doc = req.serialize2DOMDocument();
1030 		String xml = XmlUtil.node2String(doc, false, true);
1031 		assertEquals(idcard, factory.deserializeRequest(xml).getIDCard());
1032 	}
1033 
1034 	public void testIDCardNullID() throws Exception {
1035 
1036 		try {
1037 			new IDCard(null, null, null, AuthenticationLevel.MOCES_TRUSTED_USER, "certhash", "issuer", new Date(), new Date(), null, null, null) {
1038 				private static final long serialVersionUID = 1612456955426243414L;
1039 			};
1040 			fail("Should fail on null ID");
1041 		} catch (ModelException me) {
1042 			// OK!
1043 		}
1044 	}
1045 
1046 	public void testIDCardTimeValidity() throws Exception {
1047 		// Positive test
1048 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1049 		Request req = createRequestVOCES(factory, false, "testflow", false);
1050 		assertTrue(req.getIDCard().isValidInTime());
1051 
1052 		// Negative test
1053 		req = createRequestNoAuth(factory, false, "testflow",true);
1054 		Document doc = req.serialize2DOMDocument();
1055 
1056 		// Test past condition interval
1057 		Element pastConditionElement = createCondition(doc,25*HOUR_IN_MILLIS, factory);
1058 		// replace condition element <saml:Conditions NotBefore="2007-02-22T15:41:54" NotOnOrAfter="2007-02-23T15:41:54" />
1059 		req = replaceCondition(factory, doc,pastConditionElement);
1060 		assertFalse(req.getIDCard().isValidInTime());
1061 
1062 		// Test future condition element
1063 		doc = req.serialize2DOMDocument();
1064 		Element futureConditionElement = createCondition(doc,-HOUR_IN_MILLIS, factory); // Future startdate
1065 		req = replaceCondition(factory, doc,futureConditionElement);
1066 		assertFalse(req.getIDCard().isValidInTime());
1067 
1068 		// Test transition cases: future
1069 		doc = req.serialize2DOMDocument();
1070 
1071 		int s = 5000; 	// max seconds to try
1072 		int t = 200;		// number of milliseconds to move the validity period
1073 		int max = (int)Math.ceil((-0.5+Math.sqrt(0.25+2*s/t))); // Calculate max number of tries before skipping the test
1074 
1075 		int i=1;
1076 		for(;i<max; i++) { // try only up to s milliseconds, otherwise warn and skip this test
1077 			futureConditionElement = createCondition(doc,-i*t, factory); // Startdate in near future
1078 			req = replaceCondition(factory, doc,futureConditionElement);
1079 			if(!req.getIDCard().isValidInTime())
1080 				break;
1081 		}
1082 		if(i==max) {
1083 			System.out.println("Warning: startdate border transition was not tested!");
1084 		} else {
1085 			Thread.sleep(i*t);
1086 			assertTrue(req.getIDCard().isValidInTime());
1087 		}
1088 		// Test transition cases: past
1089 		doc = req.serialize2DOMDocument();
1090 		 i=1;
1091 		for(;i<max; i++) { // try only up to 10 seconds otherwise warn and skip this test
1092 			futureConditionElement = createCondition(doc,24*HOUR_IN_MILLIS-i*t, factory); // Expirydate in near future
1093 			req = replaceCondition(factory, doc,futureConditionElement);
1094 			if(req.getIDCard().isValidInTime())
1095 				break;
1096 		}
1097 		if(i==max) {
1098 			System.out.println("Warning: expirery border transition was not tested!");
1099 		} else {
1100 			Thread.sleep(i*t);
1101 			assertFalse(req.getIDCard().isValidInTime());
1102 		}
1103 	}
1104 
1105 	public void testIDCardNotPrepared() throws Exception {
1106 
1107 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1108 		Request req = createRequestVOCES(factory, false, "testflow", false);
1109 		assertNull(req.getIDCard().domElement);
1110 		try {
1111 			req.getIDCard().sign(XmlUtil.createEmptyDocument(), factory.getCredentialVault());
1112 			fail("sign() should fail if the id card has no DOM element attached");
1113 		} catch (IllegalStateException ise) {
1114 			// OK!
1115 		}
1116 
1117 		try {
1118 			req.getIDCard().injectSignature("test", factory.getCredentialVault().getSystemCredentialPair().getCertificate());
1119 			fail("injectSignature() should fail if the id card has no DOM element attached");
1120 		} catch (ModelException ise) {
1121 			// OK!
1122 		}
1123 
1124 	}
1125 
1126 	public void testIDCardVersion() throws Exception {
1127 		SOSIFactory factory = new SOSIFactory(new EmptyCredentialVault(), new Properties());
1128 		IDCard idCard = createNewUserIdCard(factory, AuthenticationLevel.MOCES_TRUSTED_USER, null, "1111111118");
1129 		assertEquals(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, idCard.getVersion());
1130 		idCard = createNewSystemIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION);
1131 		assertEquals(SOSIFactory.SOSI_DEFAULT_DGWS_VERSION, idCard.getVersion());
1132 
1133 		Properties properties = new Properties();
1134 		properties.put(SOSIFactory.PROPERTYNAME_SOSI_DGWS_VERSION, "1.0");
1135 		factory = new SOSIFactory(new EmptyCredentialVault(), properties);
1136 		idCard = createNewUserIdCard(factory, AuthenticationLevel.MOCES_TRUSTED_USER, null, "1111111118");
1137 		assertEquals("1.0", idCard.getVersion());
1138 		idCard = createNewSystemIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION);
1139 		assertEquals("1.0", idCard.getVersion());
1140 
1141 		try {
1142 			SystemInfo systemInfo = new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg"), "ItSystem");
1143 			new SystemIDCard(null, AuthenticationLevel.NO_AUTHENTICATION, "issuer", systemInfo, null, null, null, null);
1144 			fail("Should fail on empyt/null parameter");
1145 		} catch (ModelException me) {
1146 			// OK
1147 		}
1148 
1149 		try {
1150 			SystemInfo systemInfo = new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg"), "ItSystem");
1151 			new SystemIDCard(null, null, "1234", AuthenticationLevel.NO_AUTHENTICATION, null, "issuer", systemInfo, new Date(), new Date(), null, null, null);
1152 			fail("Should fail on empyt/null parameter");
1153 		} catch (ModelException me) {
1154 			// OK
1155 		}
1156 
1157 		try {
1158 			SystemInfo systemInfo = new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg"), "ItSystem");
1159 			new SystemIDCard("X.Y.Z", AuthenticationLevel.NO_AUTHENTICATION, "issuer", systemInfo, null, null, null, null);
1160 			fail("Should fail on unsupported version");
1161 		} catch (ModelException me) {
1162 			// OK
1163 		}
1164 
1165 		try {
1166 			SystemInfo systemInfo = new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg"), "ItSystem");
1167 			new SystemIDCard("X.Y.Z", null, "1234", AuthenticationLevel.NO_AUTHENTICATION, null, "issuer", systemInfo, new Date(), new Date(), null, null, null);
1168 			fail("Should fail on unsupported version");
1169 		} catch (ModelException me) {
1170 			// OK
1171 		}
1172 
1173 	}
1174 
1175 	public void testSystemInfo() throws Exception {
1176 
1177 		try {
1178 			new SystemInfo(null, "");
1179 			fail("Should fail on empyt/null parameter");
1180 		} catch (ModelException me) {
1181 			// OK
1182 		}
1183 
1184 		try {
1185 			new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"), null);
1186 			fail("Should fail on empyt/null parameter");
1187 		} catch (ModelException me) {
1188 			// OK
1189 		}
1190 
1191 		try {
1192 			new SystemInfo(new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"), "");
1193 			fail("Should fail on empyt/null parameter");
1194 		} catch (ModelException me) {
1195 			// OK
1196 		}
1197 	}
1198 
1199 	public void testUserInfo() throws Exception {
1200 		UserInfo info1 = new UserInfo("1234", "Hans", "Hansen", "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1201 		UserInfo info2 = new UserInfo("1234", "Hans", "Hansen", "hans@hansen.dk", "et eller andet stilling", "praktiserende læge", "1234");
1202 		assertFalse(info1.equals(info2));
1203 
1204 		UserInfo userInfo = new UserInfo(null, "Hans", "Hansen", "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1205 		assertEquals("", userInfo.getCPR());
1206 
1207 		try {
1208 			new UserInfo("1234", null, "Hansen", "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1209 			fail("Should fail on empyt/null parameter");
1210 		} catch (ModelException e) {
1211 			//ok
1212 		}
1213 		try {
1214 			new UserInfo("1234", "", "Hansen", "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1215 			fail("Should fail on empyt/null parameter");
1216 		} catch (ModelException e) {
1217 			//ok
1218 		}
1219 		try {
1220 			new UserInfo("1234", "Hans", null, "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1221 			fail("Should fail on empyt/null parameter");
1222 		} catch (ModelException e) {
1223 			//ok
1224 		}
1225 		try {
1226 			new UserInfo("1234", "Hans", "", "hans@hansen.dk", "læge", "praktiserende læge", "1234");
1227 			fail("Should fail on empyt/null parameter");
1228 		} catch (ModelException e) {
1229 			//ok
1230 		}
1231 		try {
1232 			new UserInfo("1234", "Hans", "Hansen", "hans@hansen.dk", "læge", null, "1234");
1233 			fail("Should fail on empyt/null parameter");
1234 		} catch (ModelException e) {
1235 			//ok
1236 		}
1237 		try {
1238 			new UserInfo("1234", "Hans", "Hansen", "hans@hansen.dk", "læge", "", "1234");
1239 			fail("Should fail on empyt/null parameter");
1240 		} catch (ModelException e) {
1241 			//ok
1242 		}
1243 
1244 		new UserInfo(null, "Hans", "Hansen", null, null, "Praktiserende læge", null);
1245 
1246 	}
1247 
1248 	public void testCareProvider() throws Exception {
1249 		try {
1250 			new CareProvider(null,"1234", "Sygehusafdeling");
1251 			fail("Should fail on empyt/null parameter");
1252 		} catch (ModelException e) {
1253 			//ok
1254 		}
1255 		try {
1256 			new CareProvider("","1234", "Sygehusafdeling");
1257 			fail("Should fail on empyt/null parameter");
1258 		} catch (ModelException e) {
1259 			//ok
1260 		}
1261 		try {
1262 			new CareProvider(SubjectIdentifierTypeValues.SKS_CODE, null, "Sygehusafdeling");
1263 			fail("Should fail on empyt/null parameter");
1264 		} catch (ModelException e) {
1265 			//ok
1266 		}
1267 		try {
1268 			new CareProvider(SubjectIdentifierTypeValues.SKS_CODE, "", "Sygehusafdeling");
1269 			fail("Should fail on empyt/null parameter");
1270 		} catch (ModelException e) {
1271 			//ok
1272 		}
1273 		try {
1274 			new CareProvider(SubjectIdentifierTypeValues.SKS_CODE, "1234", null);
1275 			fail("Should fail on empyt/null parameter");
1276 		} catch (ModelException e) {
1277 			//ok
1278 		}
1279 		try {
1280 			new CareProvider(SubjectIdentifierTypeValues.SKS_CODE, "1234", "");
1281 			fail("Should fail on empyt/null parameter");
1282 		} catch (ModelException e) {
1283 			//ok
1284 		}
1285 		try {
1286 			new CareProvider("SomeCareProviderType","1234", "Sygehusafdeling");
1287 			fail("Should fail on unknown CareProviderType");
1288 		} catch (ModelException e) {
1289 			//ok
1290 		}
1291 		try {
1292 			new CareProvider(SubjectIdentifierTypeValues.CPR_NUMBER,"1234", "Sygehusafdeling");
1293 			fail("Should fail on unknown CareProviderType");
1294 		} catch (ModelException e) {
1295 			//ok
1296 		}
1297 
1298 		new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "Organisation XYZ");
1299 		new CareProvider(SubjectIdentifierTypeValues.SKS_CODE, "1234", "Sygehusafdelingen 123");
1300 		new CareProvider(SubjectIdentifierTypeValues.Y_NUMBER, "1234", "Læge Hansen");
1301 		new CareProvider(SubjectIdentifierTypeValues.P_NUMBER, "1234", "Et eller andet organisation");
1302 
1303 	}
1304 
1305 	public void testNullFlowID() throws Exception {
1306 
1307 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1308 		Request req = createRequestVOCES(factory, false, null, false);
1309 		assertNull(req.getFlowID());
1310 		// Check that a serialization/deserialization does not break due to a
1311 		// missing flow ID
1312 		req = cloneRequestBySerialization(factory, req);
1313 		assertNull(req.getFlowID());
1314 	}
1315 
1316 	public void testSerializeUserOccupation() throws Exception {
1317 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1318 		UserIDCard idCard = createNewUserIdCard(factory, AuthenticationLevel.NO_AUTHENTICATION, null, "1234567890");
1319 		Element doc = idCard.serialize2DOMDocument(factory, XmlUtil.createEmptyDocument());
1320 		UserIDCard deserializedIDCard = (UserIDCard) factory.deserializeIDCard(XmlUtil.node2String(doc));
1321 		assertEquals(idCard, deserializedIDCard);
1322 		assertEquals(idCard.getUserInfo(), deserializedIDCard.getUserInfo());
1323 		assertEquals(idCard.getUserInfo().getOccupation(), deserializedIDCard.getUserInfo().getOccupation());
1324 	}
1325 
1326 	public void testSerializeMinimalIDCard() throws Exception {
1327 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1328 		CareProvider careProvider = new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg");
1329 		UserInfo userInfo = new UserInfo(null, "Hans", "Hansen", null, null, "Praktiserende læge", null);
1330 
1331 		UserIDCard idCard = factory.createNewUserIDCard("EMS/Harmoni", userInfo, careProvider, AuthenticationLevel.NO_AUTHENTICATION, null, null, null, "1234");
1332 		Element element = idCard.serialize2DOMDocument(factory, XmlUtil.createEmptyDocument());
1333 		String xml = XmlUtil.node2String(element, true, true);
1334 		UserIDCard deserializedIDCard = (UserIDCard) factory.deserializeIDCard(xml);
1335 		assertEquals(idCard, deserializedIDCard);
1336 
1337 		userInfo = new UserInfo("1234", "Hans", "Hansen", null, null, "Praktiserende læge", null);
1338 		idCard = factory.createNewUserIDCard("EMS/Harmoni", userInfo, careProvider, AuthenticationLevel.NO_AUTHENTICATION, null, null, null, null);
1339 		element = idCard.serialize2DOMDocument(factory, XmlUtil.createEmptyDocument());
1340 		xml = XmlUtil.node2String(element, true, true);
1341 		deserializedIDCard = (UserIDCard) factory.deserializeIDCard(xml);
1342 		assertEquals(idCard, deserializedIDCard);
1343 
1344 	}
1345 
1346 	/*
1347 	public void testDeserializeIDCardWithEmptyAttributes() throws Exception {
1348 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1349 		CareProvider careProvider = new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "1234", "SomeOrg");
1350 		UserInfo userInfo = new UserInfo(null, "Hans", "Hansen", "hans@email.com", null, "Praktiserende læge", null);
1351 
1352 		UserIDCard idCard = factory.createNewUserIDCard("EMS/Harmoni", userInfo, careProvider, AuthenticationLevel.NO_AUTHENTICATION, null, null, null, "1234");
1353 		Element element = idCard.serialize2DOMDocument(factory, XmlUtil.createEmptyDocument());
1354 		String xml = XmlUtil.node2String(element, true, true);
1355 		//xml = xml.replaceFirst("<saml:AttributeValue>hans@email.com</saml:AttributeValue>", "");
1356 		xml = xml.replaceFirst("hans@email.com", "");
1357 		System.out.println(xml);
1358 		UserIDCard deserializedIDCard = (UserIDCard) factory.deserializeIDCard(xml);
1359 
1360 	}
1361 	*/
1362 
1363 	public void testDeserializeSecurityTokenRequestEmptyCPR() throws Exception {
1364 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1365 		SecurityTokenRequest request = createSecurityTokenRequest(factory, true, false, AuthenticationLevel.MOCES_TRUSTED_USER, null);
1366 		Document doc = request.serialize2DOMDocument();
1367 		String signature = createSignature(factory, request, doc);
1368 		request.getIDCard().injectSignature(signature, factory.getCredentialVault().getSystemCredentialPair().getCertificate());
1369 		String xml = XmlUtil.node2String(doc);
1370 		SecurityTokenRequest deserializedRequest = factory.deserializeSecurityTokenRequest(xml);
1371 		assertEquals(request, deserializedRequest);
1372 	}
1373 
1374 	public void testDeserializeRequestHeader() throws Exception {
1375 		if (System.getProperty("java.specification.version").equals("1.4")) {
1376 			System.out.println("'testDeserializeRequestHeader' disabled on jdk 1.4 due to insufficient handling of namespaces in the version of Xalan shipped with the jdk.");
1377 			return;
1378 		}
1379 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1380 
1381 		Request request = createRequestVOCES(factory, true, "1234", true);
1382 		Document doc = request.serialize2DOMDocument();
1383 		Element headerNode = (Element) doc.getElementsByTagNameNS(NameSpaces.SOAP_SCHEMA, "Header").item(0);
1384 		String xml = XmlUtil.node2String(headerNode);
1385 		RequestHeader header = factory.deserializeRequestHeader(xml);
1386 
1387 		assertNotNull(header);
1388 		assertEquals(xml, XmlUtil.node2String(header.getDocument()));
1389 		assertEquals(request.getIDCard(), header.getIDCard());
1390 		assertEquals(request.getMessageID(), header.getMessageID());
1391 		// milliseconds are not serialized - ignore them!
1392 		assertEquals(Math.abs(request.getCreationDate().getTime() / 1000), Math.abs(header.getCreationDate().getTime() / 1000));
1393 		assertEquals(request.getDGWSVersion(), header.getDGWSVersion());
1394 		assertEquals(request.getFlowID(), header.getFlowID());
1395 		assertEquals(request.isDemandNonRepudiationReceipt(), header.isDemandNonRepudiationReceipt());
1396 	}
1397 
1398 	public void testDeserializeReplyHeader() throws Exception {
1399 		if (System.getProperty("java.specification.version").equals("1.4")) {
1400 			System.out.println("'testDeserializeReplyHeader' disabled on jdk 1.4 due to insufficient handling of namespaces in the version of Xalan shipped with the jdk.");
1401 			return;
1402 		}
1403 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1404 		Request request = createRequestVOCES(factory, true, "1234", true);
1405 
1406 		Reply reply = factory.createNewReply(request, FlowStatusValues.FLOW_FINALIZED_SUCCESFULLY);
1407 		reply.setIDCard(request.getIDCard());
1408 		Document doc = reply.serialize2DOMDocument();
1409 		Element headerNode = (Element) doc.getElementsByTagNameNS(NameSpaces.SOAP_SCHEMA, "Header").item(0);
1410 		String xml = XmlUtil.node2String(headerNode);
1411 		ReplyHeader header = factory.deserializeReplyHeader(xml);
1412 
1413 		assertNotNull(header);
1414 		assertEquals(xml, XmlUtil.node2String(header.getDocument()));
1415 		assertEquals(reply.getIDCard(), header.getIDCard());
1416 		assertEquals(reply.getMessageID(), header.getMessageID());
1417 		// milliseconds are not serialized - ignore them!
1418 		assertEquals(Math.abs(reply.getCreationDate().getTime() / 1000), Math.abs(header.getCreationDate().getTime() / 1000));
1419 		assertEquals(reply.getDGWSVersion(), header.getDGWSVersion());
1420 		assertEquals(reply.getFlowID(), header.getFlowID());
1421 		assertEquals(reply.getFlowStatus(), header.getFlowStatus());
1422 		assertEquals(reply.getRequestID(), header.getRequestID());
1423 
1424 		reply = factory.createNewErrorReply(request, "faultCode", "faultString");
1425 		doc = reply.serialize2DOMDocument();
1426 		headerNode = (Element) doc.getElementsByTagNameNS(NameSpaces.SOAP_SCHEMA, "Header").item(0);
1427 		xml = XmlUtil.node2String(headerNode);
1428 
1429 		try {
1430 			factory.deserializeReplyHeader(xml);
1431 			fail("Excpected ModelBuildException when deserialixing header from error reply");
1432 		} catch (ModelBuildException e) {
1433 			// Expected
1434 		}
1435 	}
1436 
1437 	public void testRequestWithoutNonRepudiation() throws Exception {
1438 		SOSIFactory factory = CredentialVaultTestUtil.createSOSIFactory();
1439 		Request request = createRequestNoAuth(factory, true, null, false);
1440 		Document doc = request.serialize2DOMDocument();
1441 		Node nonRepudiationNode = doc.getElementsByTagNameNS(NameSpaces.MEDCOM_SCHEMA, "RequireNonRepudiationReceipt").item(0);
1442 		nonRepudiationNode.getParentNode().removeChild(nonRepudiationNode);
1443 		String xml = XmlUtil.node2String(doc);
1444 		Request deserializedRequest = factory.deserializeRequest(xml);
1445 		assertFalse(deserializedRequest.isDemandNonRepudiationReceipt());
1446 	}
1447 
1448     public void __testCertificateReference() {
1449         CredentialVault credentialVault = CredentialVaultTestUtil.getVocesCredentialVault();
1450         System.out.println(credentialVault.getSystemCredentialPair().getCertificate());
1451 
1452         Properties props = SignatureUtil.setupCryptoProviderForJVM();
1453         props.put(SOSIFactory.PROPERTYNAME_SOSI_VALIDATE, "false");
1454         props.put(SOSIFactory.PROPERTYNAME_SOSI_ISSUER, "SOSI");
1455         props.put("sosi:federationcertificate.host.oces1", "dir.certifikat.dk");
1456 
1457         // Get the factory
1458         Federation sosiTestFederation = new SOSITestFederation(props, new HashMapCertificateCache());
1459         SOSIFactory factory = new SOSIFactory(sosiTestFederation, credentialVault,  props);
1460 
1461         final SystemIDCard idCard = createNewSystemIdCard(factory, AuthenticationLevel.VOCES_TRUSTED_SYSTEM);
1462         final SecurityTokenRequest request = factory.createNewSecurityTokenRequest();
1463         request.setIDCard(idCard);
1464         Document document = request.serialize2DOMDocument();
1465 
1466         System.out.println(XmlUtil.node2String(document, true, false));
1467 
1468         // udskift KeyInfo
1469 
1470         String nsSoap = "http://schemas.xmlsoap.org/soap/envelope/";
1471         String nsWst = "http://schemas.xmlsoap.org/ws/2005/02/trust";
1472         String nsSaml = "urn:oasis:names:tc:SAML:2.0:assertion";
1473         String nsDs = "http://www.w3.org/2000/09/xmldsig#";
1474 
1475         Element soapEnv = document.getDocumentElement();
1476         Element body = XmlUtil.getFirstChildElementNS(soapEnv, nsSoap, "Body");
1477         Element rst = XmlUtil.getFirstChildElementNS(body, nsWst, "RequestSecurityToken");
1478         Element claims = XmlUtil.getFirstChildElementNS(rst, nsWst, "Claims");
1479         Element assertion = XmlUtil.getFirstChildElementNS(claims, nsSaml, "Assertion");
1480         Element sig = XmlUtil.getFirstChildElementNS(assertion, nsDs, "Signature");
1481 
1482         Element keyInfo = XmlUtil.getFirstChildElementNS(sig, nsDs, "KeyInfo");
1483 
1484         Element x509Data = XmlUtil.getFirstChildElementNS(keyInfo, nsDs, "X509Data");
1485         keyInfo.removeChild(x509Data);
1486 
1487         Element keyName = document.createElementNS(nsDs, "KeyName");
1488         keyName.appendChild(document.createTextNode("OCES1,CVR:55832218-UID:1165408969529,1077391241"));
1489         keyInfo.appendChild(keyName);
1490 
1491         final String xmlString = XmlUtil.node2String(document);
1492         factory.deserializeSecurityTokenRequest(xmlString);
1493     }
1494 
1495 
1496 	// ==========================================
1497 	// Helpers
1498 	// ==========================================
1499 
1500 	private Request createRequestNoAuth(SOSIFactory factory, boolean nonRep, String flowID, boolean userIDCard) {
1501 		return createRequest(factory, nonRep, flowID, userIDCard, AuthenticationLevel.NO_AUTHENTICATION);
1502 	}
1503 
1504 	private Request createRequestVOCES(SOSIFactory factory, boolean nonRep, String flowID, boolean userIDCard) {
1505 		return createRequest(factory, nonRep, flowID, userIDCard, AuthenticationLevel.VOCES_TRUSTED_SYSTEM);
1506 	}
1507 
1508 	private Request createRequestMOCES(SOSIFactory factory, boolean nonRep, String flowID) {
1509 		return createRequest(factory, nonRep, flowID, true, AuthenticationLevel.MOCES_TRUSTED_USER);
1510 	}
1511 
1512 	private Request createRequest(SOSIFactory factory, boolean nonRep, String flowID, boolean userIDCard, AuthenticationLevel authLevel) {
1513 		return createRequest(factory, nonRep, flowID, userIDCard, authLevel, "1234567890");
1514 	}
1515 
1516 	private Request createRequest(SOSIFactory factory, boolean nonRep, String flowID, boolean userIDCard, AuthenticationLevel authLevel, String cpr) {
1517 
1518 		Request request = factory.createNewRequest(nonRep, flowID);
1519 
1520 		X509Certificate certificate = null;
1521 		if(!AuthenticationLevel.NO_AUTHENTICATION.equals(authLevel)) {
1522 			certificate = factory.getCredentialVault().getSystemCredentialPair().getCertificate();
1523 		}
1524 
1525 		if (userIDCard) {
1526 			request.setIDCard(createNewUserIdCard(factory, authLevel, certificate,cpr));
1527 		} else {
1528 			request.setIDCard(factory.createNewSystemIDCard(
1529 					"testITSystem",
1530 					new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER,
1531 					"124454",
1532 					"Hansens Praksis"),
1533 					authLevel,
1534 					null,
1535 					null,
1536 					certificate,
1537 					null));
1538 		}
1539 		return request;
1540 	}
1541 
1542 	private SecurityTokenRequest createSecurityTokenRequestVOCES(SOSIFactory factory, boolean userIDCard, boolean certificate) {
1543 		return createSecurityTokenRequest(factory, userIDCard, certificate, AuthenticationLevel.VOCES_TRUSTED_SYSTEM, "1234567890");
1544 	}
1545 
1546 	private SecurityTokenRequest createSecurityTokenRequest(SOSIFactory factory, boolean userIDCard, boolean certificate, AuthenticationLevel authLevel, String cpr) {
1547 
1548 		SecurityTokenRequest request = factory.createNewSecurityTokenRequest();
1549 
1550 		X509Certificate cert = null;
1551 		if(certificate && !AuthenticationLevel.NO_AUTHENTICATION.equals(authLevel)) {
1552 			cert = factory.getCredentialVault().getSystemCredentialPair().getCertificate();
1553 		}
1554 
1555 		if (userIDCard) {
1556 			request.setIDCard(createNewUserIdCard(factory, authLevel, cert,cpr));
1557 		} else {
1558 			request.setIDCard(factory.createNewSystemIDCard(
1559 					"testITSystem",
1560 					new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER,
1561 					"124454",
1562 					"Hansens Praksis"),
1563 					authLevel,
1564 					null,
1565 					null,
1566 					cert,
1567 					null));
1568 		}
1569 		return request;
1570 	}
1571 
1572 	private UserIDCard createNewUserIdCard(SOSIFactory factory, AuthenticationLevel authLevel, X509Certificate certificate, String cpr) {
1573 		return factory.createNewUserIDCard(
1574 				"testITSystem",
1575 				new UserInfo(cpr, "Jan", "Riis", "jan<at>lakeside.dk", "hacker", "doctor", "2101"),
1576 				new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
1577 				authLevel,
1578 				null,
1579 				null,
1580 				certificate,
1581 				null);
1582 	}
1583 
1584 	private SystemIDCard createNewSystemIdCard(SOSIFactory factory, AuthenticationLevel authLevel) {
1585 		return factory.createNewSystemIDCard(
1586 				"testITSystem",
1587 				new CareProvider(SubjectIdentifierTypeValues.CVR_NUMBER, "124454", "Hansens Praksis"),
1588 				authLevel,
1589 				null,
1590 				null,
1591 				null,
1592 				null);
1593 	}
1594 
1595 	private void signatureTest(SOSIFactory factory, Request request, Document doc) throws ModelBuildException {
1596 
1597 		// Validate the signature
1598 		Node signature = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
1599 		assertNotNull(signature);
1600 
1601 		if (!SignatureUtil.validate(signature, factory.getFederation(), factory.getCredentialVault(),true))
1602 			fail("Failed to validate signature?!");
1603 
1604 		// Simulate that the message was written to a pipe and deserialized
1605 		// again on the other side
1606 		String serialXml = XmlUtil.node2String(doc, false, true);
1607 		doc = XmlUtil.readXml(properties, serialXml, true);
1608 
1609 		signature = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Signature").item(0);
1610 
1611 		if (!SignatureUtil.validate(signature, factory.getFederation(), factory.getCredentialVault(),true))
1612 			fail("Unable to validate signature after serialization & deserialization");
1613 
1614 		Request newRequest = factory.deserializeRequest(new String(serialXml));
1615 
1616 		assertEquals(request, newRequest);
1617 	}
1618 
1619 	private String createSignature(SOSIFactory factory, Message req1, Document doc) throws NoSuchAlgorithmException, InvalidKeyException,
1620 			SignatureException {
1621 
1622 		byte[] siBytes = req1.getIDCard().getBytesForSigning(doc);
1623 		// Sign the bytes with a private key (in this case the key in credential
1624 		// vault, but that makes no difference)
1625 		Signature jceSign;
1626 		try {
1627 			jceSign = Signature.getInstance("SHA1withRSA",SignatureUtil.getCryptoProvider(factory.getProperties(),
1628 					SOSIFactory.PROPERTYNAME_SOSI_CRYPTOPROVIDER_SHA1WITHRSA));
1629 		} catch (NoSuchProviderException e) {
1630 			throw new ModelException("No Such Provider", e);
1631 		}
1632 		PrivateKey key = factory.getCredentialVault().getSystemCredentialPair().getPrivateKey();
1633 		jceSign.initSign(key);
1634 		jceSign.update(siBytes);
1635 		String signature = XmlUtil.toBase64(jceSign.sign());
1636 		return signature;
1637 	}
1638 
1639 	private Request cloneRequestBySerialization(SOSIFactory factory, Request req) throws ModelBuildException {
1640 
1641 		Document doc = req.serialize2DOMDocument();
1642 		String xml = XmlUtil.node2String(doc, false, true);
1643 		return factory.deserializeRequest(xml);
1644 	}
1645 
1646 	private Reply cloneReplyBySerialization(SOSIFactory factory, Reply rep) throws ModelBuildException {
1647 
1648 		Document doc = rep.serialize2DOMDocument();
1649 		String xml = XmlUtil.node2String(doc, false, true);
1650 		return factory.deserializeReply(xml);
1651 	}
1652 
1653 	private SecurityTokenRequest cloneSecurityTokenRequestBySerialization(SOSIFactory factory, SecurityTokenRequest securityTokenRequest)
1654 			throws ModelBuildException {
1655 
1656 		Document doc = securityTokenRequest.serialize2DOMDocument();
1657 		String xml = XmlUtil.node2String(doc, false, true);
1658 		return factory.deserializeSecurityTokenRequest(xml);
1659 	}
1660 
1661 	private SecurityTokenResponse cloneSecurityTokenResponseBySerialization(SOSIFactory factory, SecurityTokenResponse securityTokenResponse)
1662 			throws ModelBuildException {
1663 
1664 		Document doc = securityTokenResponse.serialize2DOMDocument();
1665 		String xml = XmlUtil.node2String(doc, false, true);
1666 		return factory.deserializeSecurityTokenResponse(xml);
1667 	}
1668 
1669 	private void checkBasicEquals(Object object) {
1670 
1671 		assertNotNull(object);
1672 		assertFalse(object.equals(new Object()));
1673 		assertTrue(object.equals(object));
1674 	}
1675 
1676 	private Element createCondition(Document doc, long  subtractMillis, SOSIFactory factory) {
1677 		Element newCondition = doc.createElementNS(NameSpaces.SAML2ASSERTION_SCHEMA, SAMLTags.CONDITIONS_PREFIXED);
1678 		long now = System.currentTimeMillis();
1679 		Date invalidStartDate = new Date(now-subtractMillis);
1680 		Date endDate = new Date(now-subtractMillis+24*HOUR_IN_MILLIS);
1681         boolean useZuluTime = true;
1682 		newCondition.setAttribute(SAMLAttributes.NOT_BEFORE, XmlUtil.toXMLTimeStamp(invalidStartDate, useZuluTime));
1683 		newCondition.setAttribute(SAMLAttributes.NOT_ON_OR_AFTER, XmlUtil.toXMLTimeStamp(endDate, useZuluTime));
1684 		return newCondition;
1685 	}
1686 
1687 	private Request replaceCondition(SOSIFactory factory, Document doc, Element pastConditionElement) {
1688 		Element condition =  XmlUtil.selectSingleElement(doc, "//"+SAMLTags.CONDITIONS_PREFIXED, new ModelPrefixResolver());
1689 		condition.getParentNode().replaceChild(pastConditionElement, condition);
1690 		// Deserialize document and check validity
1691 		return factory.deserializeRequest(XmlUtil.node2String(doc));
1692 	}
1693 }