Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions gamsaml20/src/main/java/com/genexus/saml20/PostBinding.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public class PostBinding extends Binding {
private static final Logger logger = LogManager.getLogger(PostBinding.class);

private Document xmlDoc;
private Document verifiedDoc;

public PostBinding() {
logger.trace("PostBinding constructor");
xmlDoc = null;
}
// EXTERNAL OBJECT PUBLIC METHODS - BEGIN

Expand All @@ -42,31 +42,39 @@ public static String logout(SamlParms parms, String relayState) {
}

public boolean verifySignatures(SamlParms parms) {
return DSig.validateSignatures(this.xmlDoc, parms.getTrustCertPath(), parms.getTrustCertAlias(), parms.getTrustCertPass());
String verified = DSig.validateSignatures(this.xmlDoc, parms.getTrustCertPath(), parms.getTrustCertAlias(), parms.getTrustCertPass());
if(verified.isEmpty()){
return false;
}else {
this.verifiedDoc = SamlAssertionUtils.loadDocument(verified);
this.xmlDoc = null;
logger.debug(MessageFormat.format("verifySignatures sanitized xmlDoc {0}", Encoding.documentToString(this.xmlDoc)));
return true;
}
}

public String getLoginAssertions() {
logger.trace("getLoginAssertions");
return SamlAssertionUtils.getLoginInfo(this.xmlDoc);
return SamlAssertionUtils.getLoginInfo(this.verifiedDoc);
}

public String getLogoutAssertions() {
logger.trace("getLogoutAssertions");
return SamlAssertionUtils.getLogoutInfo(this.xmlDoc);
return SamlAssertionUtils.getLogoutInfo(this.verifiedDoc);
}

public String getLoginAttribute(String name) {
logger.trace("getLoginAttribute");
return SamlAssertionUtils.getLoginAttribute(this.xmlDoc, name).trim();
return SamlAssertionUtils.getLoginAttribute(this.verifiedDoc, name).trim();
}

public String getRoles(String name) {
logger.debug("getRoles");
return SamlAssertionUtils.getRoles(this.xmlDoc, name);
return SamlAssertionUtils.getRoles(this.verifiedDoc, name);
}

public boolean isLogout(){
return SamlAssertionUtils.isLogout(this.xmlDoc);
return SamlAssertionUtils.isLogout(this.verifiedDoc);
}

// EXTERNAL OBJECT PUBLIC METHODS - END
Expand Down
34 changes: 27 additions & 7 deletions gamsaml20/src/main/java/com/genexus/saml20/utils/DSig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apache.xml.security.utils.Constants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.xpath.XPath;
Expand All @@ -22,38 +23,57 @@ public class DSig {

private static final Logger logger = LogManager.getLogger(DSig.class);

public static boolean validateSignatures(Document xmlDoc, String certPath, String certAlias, String certPassword) {
public static String validateSignatures(Document xmlDoc, String certPath, String certAlias, String certPassword) {
logger.trace("validateSignatures");
List<Element> assertions = new ArrayList<Element>();
X509Certificate cert = Keys.loadCertificate(certPath, certAlias, certPassword);

NodeList nodes = findElementsByPath(xmlDoc, "//*[@ID]");

NodeList signatures = xmlDoc.getElementsByTagNameNS(Constants.SignatureSpecNS, Constants._TAG_SIGNATURE);
//check the message is signed - security measure
if(signatures.getLength() == 0){
return false;
return "";
}
for (int i = 0; i < signatures.getLength(); i++) {
Element signedElement = findNodeById(nodes, getSignatureID((Element) signatures.item(i)));
assertions.add(signedElement);
if (signedElement == null) {
return false;
return "";
}
signedElement.setIdAttribute("ID", true);
try {
XMLSignature signature = new XMLSignature((Element) signatures.item(i), "");
//verifies the signature algorithm is one expected - security meassure
if (!verifySignatureAlgorithm((Element) signatures.item(i))) {
return false;
return "";
}
if (!signature.checkSignatureValue(cert)) {
return false;
return "";
}
} catch (Exception e) {
logger.error("validateSignatures", e);
return false;
return "";
}
}
return true;
return buildXml(assertions, xmlDoc);
}

public static String buildXml(List<Element> assertions, Document xmlDoc){
//security meassure against assertion manipulation, it assures that every assertion to be used on the app has been signed and verified
Element element = xmlDoc.getDocumentElement();
Node response = element.cloneNode(false);

NodeList status = element.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:protocol", "Status");
response.appendChild(status.item(0));

for(Element elem: assertions){
if(!elem.getLocalName().equals("Response")){
Node node = elem.cloneNode(true);
response.appendChild(node);
}
}
return Encoding.elementToString((Element) response);
}

private static boolean verifySignatureAlgorithm(Element elem) {
Expand Down
20 changes: 20 additions & 0 deletions gamsaml20/src/main/java/com/genexus/saml20/utils/Encoding.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import org.apache.logging.log4j.Logger;
import org.bouncycastle.util.encoders.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
Expand Down Expand Up @@ -74,6 +76,24 @@ public static String documentToString(Document doc) {
}
}

public static String elementToString(Element element) {
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();

transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(element), new StreamResult(writer));

return writer.toString();
} catch (Exception e) {
logger.error("elementToString", e);
return null;
}
}

public static byte[] decodeParameter(String parm) {
logger.trace("decodeParameter");
try {
Expand Down
1 change: 0 additions & 1 deletion gamsaml20/src/main/java/com/genexus/saml20/utils/Keys.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ private static X509Certificate loadCertificateFromJKS(String path, String alias,
logger.debug(MessageFormat.format("path: {0}, alias: {1}", path, alias));
Path p = new File(path).toPath();
logger.debug("Res path: " + p.toAbsolutePath());
System.out.println("Res path: " + p.toAbsolutePath());
try (InputStream in = new DataInputStream(Files.newInputStream(p))) {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, password.toCharArray());
Expand Down
Loading