| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** @const */ |
| const BEGIN_CERTIFICATE = '-----BEGIN CERTIFICATE-----'; |
| |
| /** @const */ |
| const END_CERTIFICATE = '-----END CERTIFICATE-----'; |
| |
| let xmlPolicy = null; |
| |
| /** |
| * With Trusted Types Content Security Policy enabled, we cannot parseFromString |
| * on untrusted content types. This class encapsulates and abstracts parsing |
| * of XML strings to reduce the risk of introducing unsafe sink assignments in |
| * other contexts. |
| */ |
| export class SafeXMLUtils { |
| constructor(xmlString) { |
| if (xmlPolicy === null) { |
| // This policy is only meant to be used for extracting value out of XML. |
| // Policy not to be used from outside of this file. |
| xmlPolicy = window.trustedTypes.createPolicy('xml-policy', { |
| createHTML: (s) => (s), |
| }); |
| } |
| const xml = xmlPolicy.createHTML(xmlString); |
| const parser = new DOMParser(); |
| this.xmlDoc = parser.parseFromString(xml, 'text/xml'); |
| } |
| |
| /** |
| * Return x509certificate in pem-format which is extracted from our xml |
| * and will be used to record SAML provider. |
| * @return {string|null} The X509Certificate if one exists, null otherwise. |
| */ |
| getX509Certificate() { |
| let certificate = this.xmlDoc.getElementsByTagName('ds:X509Certificate'); |
| if (!certificate || certificate.length === 0) { |
| // tag 'ds:X509Certificate' doesn't exist |
| certificate = this.xmlDoc.getElementsByTagName('X509Certificate'); |
| } |
| |
| if (certificate && certificate.length > 0 && certificate[0].childNodes && |
| certificate[0].childNodes[0] && |
| certificate[0].childNodes[0].nodeValue) { |
| certificate = certificate[0].childNodes[0].nodeValue; |
| return BEGIN_CERTIFICATE + '\n' + certificate.trim() + '\n' + |
| END_CERTIFICATE + '\n'; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Extracts a string from the given XML DOM, using the given query selector. |
| * @param {string} querySelectorStr The query selector to find the string. |
| * @return {string} The extracted string (empty if failed to extract). |
| */ |
| extractStringFromXml(querySelectorStr) { |
| const element = this.xmlDoc.querySelector(querySelectorStr); |
| return (element && element.textContent) ? element.textContent : ''; |
| } |
| } |