From cce257a7e03bf647d2709c2c6a2faf6c21f6aebd Mon Sep 17 00:00:00 2001 From: Alejandro Blanco Date: Wed, 14 Aug 2013 08:50:01 +0200 Subject: [PATCH 1/2] Fix parsing GeoLocation data --- samlmetajs/mdreader.js | 43 +++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/samlmetajs/mdreader.js b/samlmetajs/mdreader.js index 5a34fac..8a81348 100644 --- a/samlmetajs/mdreader.js +++ b/samlmetajs/mdreader.js @@ -790,9 +790,7 @@ parseFromString = function(xmlstring) { } - function parseUIInfo(node) { - - var mdui = {}; + function parseUIInfo(node, mdui) { expectNode(node, 'UIInfo', constants.ns.mdui); @@ -832,12 +830,6 @@ parseFromString = function(xmlstring) { } } }, - { - namespace: constants.ns.mdui, name: 'GeolocationHint', - callback: function(n) { - mdui.location = nodeGetTextRecursive(n).substr(4); - } - }, { namespace: constants.ns.mdui, name: 'Keywords', callback: function (n) { @@ -878,10 +870,27 @@ parseFromString = function(xmlstring) { processTest(new TestResult('mduiunknownchild', 'Parsing of this child element of MDUI not yet implemented [' + nodeName(n) + ']')); }); - return mdui; + } + + function parseDiscoHintsInfo(node, mdui) { + + expectNode(node, 'DiscoHints', constants.ns.mdui); + + nodeProcessChildren(node, [ + { + namespace: constants.ns.mdui, name: 'GeolocationHint', + callback: function(n) { + mdui.location = nodeGetTextRecursive(n).substr(4); + } + } + // Fallback + ], function(n) { + processTest(new TestResult('mduiunknownchild', 'Parsing of this child element of MDUI:DiscoHint not yet implemented [' + nodeName(n) + ']')); + }); } + function parseSPSSODescriptorExtensions(node, saml2sp) { expectNode(node, 'Extensions', constants.ns.md); @@ -890,7 +899,19 @@ parseFromString = function(xmlstring) { { namespace: constants.ns.mdui, name: 'UIInfo', callback: function(n) { - saml2sp.mdui = parseUIInfo(n); + if (!saml2sp.mdui) { + saml2sp.mdui = {}; + } + parseUIInfo(n, saml2sp.mdui); + } + }, + { + namespace: constants.ns.mdui, name: 'DiscoHints', + callback: function(n) { + if (!saml2sp.mdui) { + saml2sp.mdui = {}; + } + parseDiscoHintsInfo(n, saml2sp.mdui); } }, { From acc9d363c2a14781ec4357d706953a0e30f07d1d Mon Sep 17 00:00:00 2001 From: Alejandro Blanco Date: Thu, 5 Sep 2013 10:15:57 +0200 Subject: [PATCH 2/2] Validate that DiscoHints only appears on IdP Validate the XML and raise an error when a DiscoHint element appears in a SP. When serializating to XML, add only the location data to IdP. --- samlmetajs/mdreader.js | 88 ++++++++++++++++++++++++++------------ samlmetajs/samlmeta.xml.js | 3 +- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/samlmetajs/mdreader.js b/samlmetajs/mdreader.js index 8a81348..740a964 100644 --- a/samlmetajs/mdreader.js +++ b/samlmetajs/mdreader.js @@ -86,15 +86,16 @@ MDEntityDescriptor.prototype.hasCertOfType = function (type) { /* * Check if the current entity has a specified property. */ -MDEntityDescriptor.prototype.hasProperty = function (property) { - var entity; - if (hasProp(this, 'saml2sp')) { - entity = this.saml2sp; - } else { - entity = this.saml2idp; - } +MDEntityDescriptor.prototype.hasProperty = function (property, entity) { if (!entity) { - return false; + if (hasProp(this, 'saml2sp')) { + entity = this.saml2sp; + } else { + entity = this.saml2idp; + } + if (!entity) { + return false; + } } return hasProp(entity, property); @@ -103,16 +104,16 @@ MDEntityDescriptor.prototype.hasProperty = function (property) { /* * Return the specified property from the current entity. */ -MDEntityDescriptor.prototype.getProperty = function (property) { - var entity; - if (hasProp(this, 'saml2sp')) { - entity = this.saml2sp; - } else { - entity = this.saml2idp; - } +MDEntityDescriptor.prototype.getProperty = function (property, entity) { if (!entity) { - this.saml2sp = {}; - entity = this.saml2sp; + if (hasProp(this, 'saml2sp')) { + entity = this.saml2sp; + } else if (hasProp(this, 'saml2idp')) { + entity = this.saml2idp; + } else { + this.saml2sp = {}; + entity = this.saml2sp; + } } if (!hasProp(entity, property)) { @@ -125,11 +126,11 @@ MDEntityDescriptor.prototype.getProperty = function (property) { /* * Look for a MDUI property in any language. */ -MDEntityDescriptor.prototype.hasMDUIProperty = function (property) { - var mdui = this.hasProperty('mdui'), +MDEntityDescriptor.prototype.hasMDUIProperty = function (property, entity) { + var mdui = this.hasProperty('mdui', entity), result = false; if (mdui) { - mdui = this.getProperty('mdui'); + mdui = this.getProperty('mdui', entity); result = !isEmpty(mdui) && hasProp(mdui, property) && !isEmpty(mdui[property]); }; return result; @@ -165,7 +166,7 @@ MDEntityDescriptor.prototype.addLogo = function (lang, location, width, height) * Look for location. */ MDEntityDescriptor.prototype.hasLocation = function () { - return this.hasMDUIProperty('location'); + return this.hasMDUIProperty('location', this.saml2idp); }; /* @@ -175,7 +176,7 @@ MDEntityDescriptor.prototype.getLocation = function () { if (!this.hasLocation()) { return null; } else { - return this.getProperty('mdui').location; + return this.getProperty('mdui', this.saml2idp).location; } }; @@ -184,7 +185,7 @@ MDEntityDescriptor.prototype.getLocation = function () { * nested structures as needed. */ MDEntityDescriptor.prototype.setLocation = function (location) { - var mdui = this.getProperty('mdui'); + var mdui = this.getProperty('mdui', this.saml2idp); mdui.location = location; }; @@ -908,10 +909,7 @@ parseFromString = function(xmlstring) { { namespace: constants.ns.mdui, name: 'DiscoHints', callback: function(n) { - if (!saml2sp.mdui) { - saml2sp.mdui = {}; - } - parseDiscoHintsInfo(n, saml2sp.mdui); + processTest(new TestResult('extillegalelementdiscohints', 'Illegal element (DiscoHints) in MDUI Extensions at SPSSODescriptor [' + nodeName(n) + ']', 0, 2)); } }, { @@ -1031,6 +1029,36 @@ parseFromString = function(xmlstring) { return saml2sp; } + function parseIDPSSODescriptorExtensions(node, saml2idp) { + expectNode(node, 'Extensions', constants.ns.md); + + // Process children of Extensions + nodeProcessChildren(node, [ + { + namespace: constants.ns.mdui, name: 'UIInfo', + callback: function(n) { + if (!saml2idp.mdui) { + saml2idp.mdui = {}; + } + parseUIInfo(n, saml2idp.mdui); + } + }, + { + namespace: constants.ns.mdui, name: 'DiscoHints', + callback: function(n) { + if (!saml2idp.mdui) { + saml2idp.mdui = {}; + } + parseDiscoHintsInfo(n, saml2idp.mdui); + } + } + // Fallback + ], function(n) { + processTest(new TestResult('notimplementedssoext', 'Parsing Extensions at IDPSSODescriptor with [' + nodeName(n) + '] not implemented')); + // console.log('Parsing Extensions at SPSSODescriptor with [' + nodeName(n) + '] not implemented...'); + }); + } + function parseSAML2IDP(node) { var @@ -1041,6 +1069,12 @@ parseFromString = function(xmlstring) { // Process children of IDPSSODescriptor nodeProcessChildren(node, [ + { + namespace: constants.ns.md, name: 'Extensions', + callback: function(n) { + parseIDPSSODescriptorExtensions(n, saml2idp); + } + }, { namespace: constants.ns.md, name: 'KeyDescriptor', callback: function(n) { diff --git a/samlmetajs/samlmeta.xml.js b/samlmetajs/samlmeta.xml.js index 645adfe..f02fb91 100644 --- a/samlmetajs/samlmeta.xml.js +++ b/samlmetajs/samlmeta.xml.js @@ -156,7 +156,6 @@ SAMLmetaJS.xmlupdater = function(xmlstring) { entitydescriptor.hasLogo() || entitydescriptor.hasInformationURL() || entitydescriptor.hasPrivacyStatementURL() || - entitydescriptor.hasLocation() || entitydescriptor.hasKeywords ) { extensions = this.addIfNotExtensions(spdescriptor); @@ -339,7 +338,7 @@ SAMLmetaJS.xmlupdater = function(xmlstring) { } } SAMLmetaJS.XML.wipeChildren(node.parentNode, SAMLmetaJS.Constants.ns.mdui, 'DiscoHints'); - if (entitydescriptor.hasLocation()) { + if (endpoint === "saml2idp" && entitydescriptor.hasLocation()) { this.addMDUILocation(node.parentNode, entitydescriptor.getLocation()); } },