package com.onelogin.jira.saml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Response {

	private Document xmlDoc;
	private AccountSettings accountSettings;
	private Certificate certificate;

	public Response(AccountSettings accountSettings) throws CertificateException {
		this.accountSettings = accountSettings;
		certificate = new Certificate();
		certificate.loadCertificate(this.accountSettings.getCertificate());
	}

	public void loadXml(String xml) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory fty = DocumentBuilderFactory.newInstance();
		fty.setNamespaceAware(true);
		DocumentBuilder builder = fty.newDocumentBuilder();
		ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
		xmlDoc = builder.parse(bais);		
	}


	public void loadXmlFromBase64(String response) throws ParserConfigurationException, SAXException, IOException {
		Base64 base64 = new Base64();
		byte [] decodedB = base64.decode(response);		
		String decodedS = new String(decodedB);				
		loadXml(decodedS);	
	}

	public boolean isValid() throws Exception {
		NodeList nodes = xmlDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

		if(nodes==null || nodes.getLength()==0){
			throw new Exception("Can't find signature in document.");
		}

		X509Certificate cert = certificate.getX509Cert();		
		DOMValidateContext ctx = new DOMValidateContext(cert.getPublicKey() , nodes.item(0));				
		XMLSignatureFactory sigF = XMLSignatureFactory.getInstance("DOM");
		XMLSignature xmlSignature = sigF.unmarshalXMLSignature(ctx);

		return xmlSignature.validate(ctx);
	}

	public String getNameId() throws Exception {
		NodeList nodes = xmlDoc.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "NameID");		

		if(nodes.getLength()==0){
			throw new Exception("No name id found in document");
		}		

		return nodes.item(0).getTextContent();
	}
        
        
        public String getIssuer() throws Exception {
		NodeList nodes = xmlDoc.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Issuer");		

		if(nodes.getLength()==0){
			throw new Exception("No issuer found in document");
		}		

		return nodes.item(0).getTextContent();
	}
        
        
        
}
@@ -182,16 +182,130 @@
 ficate;%0A
+import java.text.DateFormat;%0Aimport java.text.SimpleDateFormat;%0Aimport java.util.Date;%0Aimport java.util.TimeZone;%0A
 import j
@@ -339,16 +339,16 @@
 nature;%0A
-
 import j
@@ -2231,16 +2231,86 @@
 (ctx);%0A%0A
+        if (!isAllowedDate())%0A        %09return false;%0A                %0A
 %09%09return
@@ -2941,31 +2941,31 @@
 %09%7D%0A        %0A
-
         
 %0A        %0A%7D
@@ -2945,27 +2945,1289 @@
        %0A        
+public boolean isAllowedDate() throws Exception %7B%0A            NodeList confirmationData = xmlDoc.getElementsByTagNameNS(%22urn:oasis:names:tc:SAML:2.0:assertion%22, %22Conditions%22);%0A            if(confirmationData.getLength()==0)%7B%0A%09%09%09throw new Exception(%22No conditions were found in document%22);%0A%09%09%7D%0A        %0A            DateFormat m_ISO8601Local = new SimpleDateFormat (%22yyyy-MM-dd'T'HH:mm:ss'Z'%22);%0A            m_ISO8601Local.setTimeZone(TimeZone.getTimeZone(%22UTC%22));%0A%0A            Date now = new Date();%0A            Date notBeforeTime = m_ISO8601Local.parse(confirmationData.item(0).%0A                                                           getAttributes().%0A                                                           getNamedItem(%22NotBefore%22).%0A                                                           getNodeValue());%0A            %0A            Date notOnOrAfterTime = m_ISO8601Local.parse(confirmationData.item(0).%0A                                                           getAttributes().%0A                                                           getNamedItem(%22NotOnOrAfter%22).%0A                                                           getNodeValue());%0A                    %0A            return (now.after(notBeforeTime) && now.before(notOnOrAfterTime));%0A        %7D
 %0A        %0A%7D

check if the current date falls into the acceptable range defined by the saml assertion