Skip to content

Commit

Permalink
Replace xpath.js with xpath
Browse files Browse the repository at this point in the history
xpath.js was forked and has since been more actively maintained
than the original, so switch to using that instead

This commit seeks to resolve the issues found in #165 by
using the abovementioned package to avoid a possible bug
with xpath.js. See #165 for further information
  • Loading branch information
LoneRifle committed Jan 1, 2019
1 parent 8d31ffd commit 1027f79
Show file tree
Hide file tree
Showing 18 changed files with 66 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ You might find it difficult to guess such transforms, but there are typical tran

### xpath

See [xpath.js](https://github.com/yaronn/xpath.js) for usage
See [xpath](https://github.com/goto100/xpath) for usage

### SignedXml

Expand Down
2 changes: 1 addition & 1 deletion example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function signXml(xml, xpath, key, dest)
function validateXml(xml, key)
{
var doc = new dom().parseFromString(xml)
var signature = select(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0]
var signature = select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0]
var sig = new SignedXml()
sig.keyInfoProvider = new FileKeyInfo(key)
sig.loadSignature(signature.toString())
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
module.exports = require('./lib/signed-xml')
module.exports.xpath = require('xpath.js')
module.exports.xpath = require('xpath').select
4 changes: 2 additions & 2 deletions lib/enveloped-signature.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
var xpath = require('xpath.js');
var xpath = require('xpath');

exports.EnvelopedSignature = EnvelopedSignature;

function EnvelopedSignature() {
}

EnvelopedSignature.prototype.process = function (node) {
var signature = xpath(node, "./*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("./*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", node)[0];
if (signature) signature.parentNode.removeChild(signature);
return node;
};
Expand Down
21 changes: 10 additions & 11 deletions lib/signed-xml.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
var select = require('xpath.js')
var xpath = require('xpath')
, Dom = require('xmldom').DOMParser
, utils = require('./utils')
, c14n = require('./c14n-canonicalization')
, execC14n = require('./exclusive-canonicalization')
, EnvelopedSignature = require('./enveloped-signature').EnvelopedSignature
, crypto = require('crypto')
, fs = require('fs')
, xpath = require('xpath.js')

exports.SignedXml = SignedXml
exports.FileKeyInfo = FileKeyInfo
Expand Down Expand Up @@ -209,7 +208,7 @@ function HMACSHA1() {
* @returns {Array} i.e. [{prefix: "saml", namespaceURI: "urn:oasis:names:tc:SAML:2.0:assertion"}]
*/
function findAncestorNs(doc, docSubsetXpath){
var docSubset = xpath(doc, docSubsetXpath);
var docSubset = xpath.select(docSubsetXpath, doc);

if(!Array.isArray(docSubset) || docSubset.length < 1){
return [];
Expand Down Expand Up @@ -418,7 +417,7 @@ SignedXml.prototype.validateReferences = function(doc) {
var elemXpath;

if (uri=="") {
elem = select(doc, "//*")
elem = xpath.select("//*", doc)
}
else if (uri.indexOf("'") != -1) {
// xpath injection
Expand All @@ -429,7 +428,7 @@ SignedXml.prototype.validateReferences = function(doc) {
for (var index in this.idAttributes) {
if (!this.idAttributes.hasOwnProperty(index)) continue;
var tmp_elemXpath = "//*[@*[local-name(.)='" + this.idAttributes[index] + "']='" + uri + "']";
var tmp_elem = select(doc, tmp_elemXpath)
var tmp_elem = xpath.select(tmp_elemXpath, doc)
num_elements_for_id += tmp_elem.length;
if (tmp_elem.length > 0) {
elem = tmp_elem;
Expand Down Expand Up @@ -519,15 +518,15 @@ SignedXml.prototype.loadSignature = function(signatureNode) {

this.signatureXml = signatureNode.toString();

var nodes = select(signatureNode, ".//*[local-name(.)='CanonicalizationMethod']/@Algorithm")
var nodes = xpath.select(".//*[local-name(.)='CanonicalizationMethod']/@Algorithm", signatureNode)
if (nodes.length==0) throw new Error("could not find CanonicalizationMethod/@Algorithm element")
this.canonicalizationAlgorithm = nodes[0].value

this.signatureAlgorithm =
utils.findFirst(signatureNode, ".//*[local-name(.)='SignatureMethod']/@Algorithm").value

this.references = []
var references = select(signatureNode, ".//*[local-name(.)='SignedInfo']/*[local-name(.)='Reference']")
var references = xpath.select(".//*[local-name(.)='SignedInfo']/*[local-name(.)='Reference']", signatureNode)
if (references.length == 0) throw new Error("could not find any Reference elements")

for (var i in references) {
Expand All @@ -539,7 +538,7 @@ SignedXml.prototype.loadSignature = function(signatureNode) {
this.signatureValue =
utils.findFirst(signatureNode, ".//*[local-name(.)='SignatureValue']/text()").data.replace(/\r?\n/g, '')

this.keyInfo = select(signatureNode, ".//*[local-name(.)='KeyInfo']")
this.keyInfo = xpath.select(".//*[local-name(.)='KeyInfo']", signatureNode)
}

/**
Expand Down Expand Up @@ -576,7 +575,7 @@ SignedXml.prototype.loadReference = function(ref) {
transforms.push(utils.findAttr(trans, "Algorithm").value)
}

var inclusiveNamespaces = select(transformsNode, "//*[local-name(.)='InclusiveNamespaces']");
var inclusiveNamespaces = xpath.select("//*[local-name(.)='InclusiveNamespaces']", transformsNode);
if (inclusiveNamespaces.length > 0) {
inclusiveNamespacesPrefixList = inclusiveNamespaces[0].getAttribute('PrefixList');
}
Expand Down Expand Up @@ -685,7 +684,7 @@ SignedXml.prototype.computeSignature = function(xml, opts) {

var signatureDoc = new Dom().parseFromString(this.signatureXml)

var referenceNode = select(doc, location.reference);
var referenceNode = xpath.select(location.reference, doc);

if (!referenceNode || referenceNode.length === 0) {
throw new Error("the following xpath cannot be used because it was not found: " + location.reference);
Expand Down Expand Up @@ -736,7 +735,7 @@ SignedXml.prototype.createReferences = function(doc, prefix) {
if (!this.references.hasOwnProperty(n)) continue;

var ref = this.references[n]
, nodes = select(doc, ref.xpath)
, nodes = xpath.select(ref.xpath, doc)

if (nodes.length==0) {
throw new Error('the following xpath cannot be signed because it was not found: ' + ref.xpath)
Expand Down
4 changes: 2 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var select = require('xpath.js');
var select = require('xpath').select

function findAttr(node, localName, namespace) {
for (var i = 0; i<node.attributes.length; i++) {
Expand All @@ -12,7 +12,7 @@ function findAttr(node, localName, namespace) {
}

function findFirst(doc, xpath) {
var nodes = select(doc, xpath)
var nodes = select(xpath, doc)
if (nodes.length==0) throw "could not find xpath " + xpath
return nodes[0]
}
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
],
"dependencies": {
"xmldom": "0.1.27",
"xpath.js": ">=0.0.3"
"xpath": "0.0.27"
},
"devDependencies": {
"nodeunit": "^0.11.3"
Expand Down
4 changes: 2 additions & 2 deletions test/c14n-non-exclusive-unit-test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
var C14nCanonicalization = require("../lib/c14n-canonicalization").C14nCanonicalization
, Dom = require('xmldom').DOMParser
, select = require('xpath.js')
, select = require('xpath').select
, findAncestorNs = require('../lib/signed-xml').SignedXml.findAncestorNs

var test_C14nCanonicalization = function(test, xml, xpath, expected) {
var doc = new Dom().parseFromString(xml);
var elem = select(doc, xpath)[0];
var elem = select(xpath, doc)[0];
var can = new C14nCanonicalization();
var result = can.process(elem, {
ancestorNamespaces: findAncestorNs(doc, xpath)
Expand Down
8 changes: 4 additions & 4 deletions test/c14nWithComments-unit-tests.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
var c14nWithComments = require("../lib/exclusive-canonicalization").ExclusiveCanonicalizationWithComments
, Dom = require('xmldom').DOMParser
, select = require('xpath.js')
, select = require('xpath').select
, SignedXml = require('../lib/signed-xml.js').SignedXml


var compare = function(test, xml, xpath, expected, inclusiveNamespacesPrefixList) {
test.expect(1)
var doc = new Dom().parseFromString(xml)
var elem = select(doc, xpath)[0]
var elem = select(xpath, doc)[0]
var can = new c14nWithComments()
var result = can.process(elem, { inclusiveNamespacesPrefixList: inclusiveNamespacesPrefixList }).toString()

Expand Down Expand Up @@ -345,7 +345,7 @@ module.exports = {
"Multiple Canonicalization with namespace definition outside of signed element": function (test) {
//var doc = new Dom().parseFromString("<x xmlns:p=\"myns\"><p:y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y></x>")
var doc = new Dom().parseFromString("<x xmlns:p=\"myns\"><p:y></p:y></x>")
var node = select(doc, "//*[local-name(.)='y']")[0]
var node = select("//*[local-name(.)='y']", doc)[0]
var sig = new SignedXml()
var res = sig.getCanonXml(["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"], node)
test.equal("<p:y xmlns:p=\"myns\"></p:y>", res)
Expand All @@ -358,7 +358,7 @@ module.exports = {
// in a document.
var xml = '<x><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" /><y><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" /></y></x>';
var doc = new Dom().parseFromString(xml);
var node = select(doc, "//*[local-name(.)='y']")[0];
var node = select("//*[local-name(.)='y']", doc)[0];
var sig = new SignedXml();
var transforms = ["http://www.w3.org/2000/09/xmldsig#enveloped-signature"];
var res = sig.getCanonXml(transforms, node);
Expand Down
8 changes: 4 additions & 4 deletions test/canonicalization-unit-tests.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
var ExclusiveCanonicalization = require("../lib/exclusive-canonicalization").ExclusiveCanonicalization
, Dom = require('xmldom').DOMParser
, select = require('xpath.js')
, select = require('xpath').select
, SignedXml = require('../lib/signed-xml.js').SignedXml


var compare = function(test, xml, xpath, expected, inclusiveNamespacesPrefixList, defaultNsForPrefix, ancestorNamespaces) {
test.expect(1)
var doc = new Dom().parseFromString(xml)
var elem = select(doc, xpath)[0]
var elem = select(xpath, doc)[0]
var can = new ExclusiveCanonicalization()
var result = can.process(elem, {
inclusiveNamespacesPrefixList: inclusiveNamespacesPrefixList,
Expand Down Expand Up @@ -381,7 +381,7 @@ module.exports = {
"Multiple Canonicalization with namespace definition outside of signed element": function (test) {
//var doc = new Dom().parseFromString("<x xmlns:p=\"myns\"><p:y><ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"></ds:Signature></p:y></x>")
var doc = new Dom().parseFromString("<x xmlns:p=\"myns\"><p:y></p:y></x>")
var node = select(doc, "//*[local-name(.)='y']")[0]
var node = select("//*[local-name(.)='y']", doc)[0]
var sig = new SignedXml()
var res = sig.getCanonXml(["http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2001/10/xml-exc-c14n#"], node)
test.equal("<p:y xmlns:p=\"myns\"></p:y>", res)
Expand All @@ -394,7 +394,7 @@ module.exports = {
// in a document.
var xml = '<x><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" /><y><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" /></y></x>';
var doc = new Dom().parseFromString(xml);
var node = select(doc, "//*[local-name(.)='y']")[0];
var node = select("//*[local-name(.)='y']", doc)[0];
var sig = new SignedXml();
var transforms = ["http://www.w3.org/2000/09/xmldsig#enveloped-signature"];
var res = sig.getCanonXml(transforms, node);
Expand Down
3 changes: 2 additions & 1 deletion test/document-test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
var crypto = require('../index');
var xpath = require('xpath');
var xmldom = require('xmldom');
var fs = require('fs');

exports['test with a document '] = function (test) {
var xml = fs.readFileSync('./test/static/valid_saml.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = new xmldom.DOMParser().parseFromString(crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0].toString());
var signature = new xmldom.DOMParser().parseFromString(xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0].toString());
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/feide_public.pem");
sig.loadSignature(signature);
Expand Down
7 changes: 4 additions & 3 deletions test/hmac-tests.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
var crypto = require('../index');
var xpath = require('xpath');
var xmldom = require('xmldom');
var fs = require('fs');

exports['test validating HMAC signature'] = function (test) {
var xml = fs.readFileSync('./test/static/hmac_signature.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/hmac.key");
sig.loadSignature(signature);
Expand All @@ -17,7 +18,7 @@ exports['test validating HMAC signature'] = function (test) {
exports['test HMAC signature with incorrect key'] = function (test) {
var xml = fs.readFileSync('./test/static/hmac_signature.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/hmac-foobar.key");
sig.loadSignature(signature);
Expand All @@ -40,7 +41,7 @@ exports['test create and validate HMAC signature'] = function (test) {
sig.computeSignature(xml);

var doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());
var signature = crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var verify = new crypto.SignedXml();
verify.keyInfoProvider = new crypto.FileKeyInfo("./test/static/hmac.key");
verify.loadSignature(signature);
Expand Down
15 changes: 8 additions & 7 deletions test/saml-response-test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
var crypto = require('../index');
var xpath = require('xpath');
var xmldom = require('xmldom');
var fs = require('fs');

exports['test validating SAML response'] = function (test) {
var xml = fs.readFileSync('./test/static/valid_saml.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/feide_public.pem");
sig.loadSignature(signature);
Expand All @@ -17,8 +18,8 @@ exports['test validating SAML response'] = function (test) {
exports['test validating wrapped assertion signature'] = function (test) {
var xml = fs.readFileSync('./test/static/valid_saml_signature_wrapping.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var assertion = crypto.xpath(doc, "//*[local-name(.)='Assertion']")[0];
var signature = crypto.xpath(assertion, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var assertion = xpath.select("//*[local-name(.)='Assertion']", doc)[0];
var signature = xpath.select("//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", assertion)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/feide_public.pem");
sig.loadSignature(signature);
Expand All @@ -37,7 +38,7 @@ exports['test validating wrapped assertion signature'] = function (test) {
exports['test validating SAML response where a namespace is defined outside the signed element'] = function (test) {
var xml = fs.readFileSync('./test/static/saml_external_ns.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = crypto.xpath(doc, "//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("//*//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/saml_external_ns.pem");
sig.loadSignature(signature);
Expand All @@ -49,8 +50,8 @@ exports['test validating SAML response where a namespace is defined outside the
exports['test reference id does not contain quotes'] = function (test) {
var xml = fs.readFileSync('./test/static/id_with_quotes.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var assertion = crypto.xpath(doc, "//*[local-name(.)='Assertion']")[0];
var signature = crypto.xpath(assertion, "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var assertion = xpath.select("//*[local-name(.)='Assertion']", doc)[0];
var signature = xpath.select("//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", assertion)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/feide_public.pem");
sig.loadSignature(signature);
Expand All @@ -67,7 +68,7 @@ exports['test reference id does not contain quotes'] = function (test) {
exports['test validating SAML response WithComments'] = function (test) {
var xml = fs.readFileSync('./test/static/valid_saml_withcomments.xml', 'utf-8');
var doc = new xmldom.DOMParser().parseFromString(xml);
var signature = crypto.xpath(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];
var signature = xpath.select("/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new crypto.SignedXml();
sig.keyInfoProvider = new crypto.FileKeyInfo("./test/static/feide_public.pem");
sig.loadSignature(signature);
Expand Down
Loading

0 comments on commit 1027f79

Please sign in to comment.