def decrypt_element(encrypted_data, key, debug=False): """ Decrypts an encrypted element. :param encrypted_data: The encrypted data. :type: lxml.etree.Element | DOMElement | basestring :param key: The key. :type: string :param debug: Activate the xmlsec debug :type: bool :returns: The decrypted element. :rtype: lxml.etree.Element """ if isinstance(encrypted_data, Element): encrypted_data = fromstring(str(encrypted_data.toxml())) elif isinstance(encrypted_data, basestring): encrypted_data = fromstring(str(encrypted_data)) xmlsec.initialize() if debug: xmlsec.set_error_callback(print_xmlsec_errors) mngr = xmlsec.KeysMngr() key = xmlsec.Key.loadMemory(key, xmlsec.KeyDataFormatPem, None) mngr.addKey(key) enc_ctx = xmlsec.EncCtx(mngr) return enc_ctx.decrypt(encrypted_data)
def parse_xml(self, text): """Wrapper for parsing XML.""" text = ''.join( ('<weblate>', strip_entities(text), '</weblate>') ) if six.PY2: return lxml.fromstring(text.encode('utf-8')) return lxml.fromstring(text)
def get_root(self, data): if isinstance(data, (str, bytes)): return fromstring(data, parser=self.parser) elif isinstance(data, stdlibElementTree.Element): # TODO: add debug level logging statement re: performance impact here return fromstring(stdlibElementTree.tostring(data, encoding="utf-8")) else: # HACK: deep copy won't keep root's namespaces resulting in an invalid digest # We use a copy so we can modify the tree # TODO: turn this off for xmlenc return fromstring(etree.tostring(data))
def xml_tree(self): """ Parse the infile with lxml and add the proper namespace if required. :return etree.ElementTree: An lxml ElementTree with proper namespace """ if hasattr(self.infile, 'seek'): self.infile.seek(0) tree = lxml.parse(self.infile) if self.meta.namespaces: return tree log.debug('Adding namespaces to xml for validation') root = tree.getroot() ns_root = etree.Element( tree.docinfo.root_name, root.attrib, nsmap={None: self.meta.get_ns_string()} ) ns_root[:] = root[:] # Roundtrip to add namespace doc = lxml.tostring( ns_root, encoding=tree.docinfo.encoding, xml_declaration=True, pretty_print=True ) ns_tree = lxml.fromstring(doc) return etree.ElementTree(ns_tree)
def parse_xml(content, transport, base_url=None, settings=None): """Parse an XML string and return the root Element. :param content: The XML string :type content: str :param transport: The transport instance to load imported documents :type transport: zeep.transports.Transport :param base_url: The base url of the document, used to make relative lookups absolute. :type base_url: str :param settings: A zeep.settings.Settings object containing parse settings. :type settings: zeep.settings.Settings :returns: The document root :rtype: lxml.etree._Element """ settings = settings or Settings() recover = not settings.strict parser = etree.XMLParser( remove_comments=True, resolve_entities=False, recover=recover, huge_tree=settings.xml_huge_tree) parser.resolvers.add(ImportResolver(transport)) try: return fromstring( content, parser=parser, base_url=base_url, forbid_dtd=settings.forbid_dtd, forbid_entities=settings.forbid_entities) except etree.XMLSyntaxError as exc: raise XMLSyntaxError( "Invalid XML content received (%s)" % exc.msg, content=content )
def import_workflow(workflow, workflow_definition, metadata=None, fs=None): # Parse Workflow Definition workflow_definition_root = fromstring(workflow_definition) if workflow_definition_root is None: raise RuntimeError(_("Could not find any nodes in Workflow definition. Maybe it's malformed?")) return import_workflow_root(workflow, workflow_definition_root, metadata, fs)
def decrypt_element(encrypted_data, key, debug=False, inplace=False): """ Decrypts an encrypted element. :param encrypted_data: The encrypted data. :type: lxml.etree.Element | DOMElement | basestring :param key: The key. :type: string :param debug: Activate the xmlsec debug :type: bool :param inplace: update passed data with decrypted result :type: bool :returns: The decrypted element. :rtype: lxml.etree.Element """ if isinstance(encrypted_data, Element): encrypted_data = fromstring(str(encrypted_data.toxml())) if not inplace and isinstance(encrypted_data, OneLogin_Saml2_XML._element_class): encrypted_data = deepcopy(encrypted_data) elif isinstance(encrypted_data, OneLogin_Saml2_XML._text_class): encrypted_data = OneLogin_Saml2_XML._parse_etree(encrypted_data) xmlsec.enable_debug_trace(debug) manager = xmlsec.KeysManager() manager.add_key(xmlsec.Key.from_memory(key, xmlsec.KeyFormat.PEM, None)) enc_ctx = xmlsec.EncryptionContext(manager) return enc_ctx.decrypt(encrypted_data)
def get_metadata(url): """ Get the metadata XML from the provided URL :param url: Url where the XML of the Identity Provider Metadata is published. :type url: string :returns: metadata XML :rtype: string """ valid = False response = urllib2.urlopen(url) xml = response.read() if xml: try: dom = fromstring(xml) idp_descriptor_nodes = OneLogin_Saml2_Utils.query(dom, '//md:IDPSSODescriptor') if idp_descriptor_nodes: valid = True except: pass if not valid: raise Exception('Not valid IdP XML found from URL: %s' % (url)) return xml
def parse_xml(content, base_url=None, recover=False): parser = etree.XMLParser( remove_comments=True, recover=recover, resolve_entities=False) try: return fromstring(content, parser=parser, base_url=base_url) except etree.XMLSyntaxError as exc: raise XMLSyntaxError("Invalid XML content received (%s)" % exc)
def process_reply(self, operation, response): if response.status_code != 200: return self.process_error(response.content) raise NotImplementedError("No error handling yet!") envelope = fromstring(response.content) return operation.process_reply(envelope)
def process_reply(self, client, operation, response): """Process the XML reply from the server. :param client: The client with which the operation was called :type client: zeep.client.Client :param operation: The operation object from which this is a reply :type operation: zeep.wsdl.definitions.Operation :param response: The response object returned by the remote server :type response: requests.Response """ if response.status_code != 200 and not response.content: raise TransportError( u'Server returned HTTP status %d (no content available)' % response.status_code) try: doc = fromstring(response.content) except etree.XMLSyntaxError: raise TransportError( u'Server returned HTTP status %d (%s)' % (response.status_code, response.content)) if client.wsse: client.wsse.verify(doc) if response.status_code != 200: return self.process_error(doc) return operation.process_reply(doc)
def parse_xml(content, transport, base_url=None, strict=True, xml_huge_tree=False): """Parse an XML string and return the root Element. :param content: The XML string :type content: str :param transport: The transport instance to load imported documents :type transport: zeep.transports.Transport :param base_url: The base url of the document, used to make relative lookups absolute. :type base_url: str :param strict: boolean to indicate if the lxml should be parsed a 'strict'. If false then the recover mode is enabled which tries to parse invalid XML as best as it can. :param xml_huge_tree: boolean to indicate if lxml should process very large XML content. :type strict: boolean :returns: The document root :rtype: lxml.etree._Element """ recover = not strict parser = etree.XMLParser(remove_comments=True, resolve_entities=False, recover=recover, huge_tree=xml_huge_tree) parser.resolvers.add(ImportResolver(transport)) try: return fromstring(content, parser=parser, base_url=base_url) except etree.XMLSyntaxError as exc: raise XMLSyntaxError( "Invalid XML content received (%s)" % exc.msg, content=content )
def parse_xml(content, transport, parser_context=None, base_url=None): parser = etree.XMLParser(remove_comments=True) parser.resolvers.add(ImportResolver(transport, parser_context)) try: return fromstring(content, parser=parser, base_url=base_url) except etree.XMLSyntaxError as exc: raise XMLSyntaxError("Invalid XML content received (%s)" % exc.message)
def __init__(self, data, digest_algorithm="sha256"): self.digest_alg = digest_algorithm self.signature_alg = None self._namespaces = dict(ds=namespaces.ds) self.data = data if isinstance(data, stdlibElementTree.Element): # TODO: add debug level logging statement re: performance impact here self.data = fromstring(stdlibElementTree.tostring(data, encoding="utf-8"))
def __query(self, query): """ Extracts a node from the DOMDocument (Logout Response Menssage) :param query: Xpath Expresion :type query: string :return: The queried node :rtype: DOMNodeList """ # Switch to lxml for querying xml = self.document.toxml() return OneLogin_Saml2_Utils.query(fromstring(xml), query)
def _get_payload_c14n(self, method, c14n_algorithm=default_c14n_algorithm): self.payload = self.data self.sig_root = Element(ds_tag("Signature"), nsmap=self.namespaces) if method == methods.enveloped: if isinstance(self.data, (str, bytes)): raise InvalidInput( "When using enveloped signature, **data** must be an XML element") signature_placeholders = self._findall( self.data, "Signature[@Id='placeholder']", anywhere=True) payload_to_sign = self.payload if self._reference_uri: payload_to_sign = self.data.find( ".//*[@Id='{}']".format( self._reference_uri.replace('#', ''))) if not payload_to_sign: raise InvalidInput( "Reference URI could not be located in the document") c14n_payload = fromstring(etree.tostring(payload_to_sign)) if len(signature_placeholders) == 0: self.payload.append(self.sig_root) elif len(signature_placeholders) == 1: self.sig_root = signature_placeholders[0] del self.sig_root.attrib["Id"] _remove_sig(self._findall(c14n_payload, "Signature[@Id='placeholder']", anywhere=True)[0]) else: raise InvalidInput("Enveloped signature input contains more than one placeholder") if self._reference_uri is None: self._reference_uri = "" # get signed data id attribute value for reference uri payloadId = self.payload.get("Id", self.payload.get("ID")) if payloadId is not None: # set default reference uri based on data id attribute value self._reference_uri = "#{}".format(payloadId) elif method == methods.detached: if self._reference_uri is None: self._reference_uri = "#{}".format(self.payload.get("Id", self.payload.get("ID", "object"))) c14n_payload = self.payload else: self.payload = Element(ds_tag("Object"), nsmap=self.namespaces, Id="object") if isinstance(self.data, (str, bytes)): self.payload.text = self.data else: self.payload.append(self.data) self._reference_uri = "#object" c14n_payload = self.payload c14n = self._c14n(c14n_payload, algorithm=c14n_algorithm) return c14n
def parse_xml(self, text, wrap=None): """Wrapper for parsing XML.""" if wrap is None: # Detect whether wrapping is desired try: return self.parse_xml(text, True), True except SyntaxError: return self.parse_xml(text, False), False text = strip_entities(text) if wrap: text = '<weblate>{}</weblate>'.format(text) return lxml.fromstring(text.encode('utf-8'))
def decrypt_element(encrypted_data, key, debug=False, inplace=False): """ Decrypts an encrypted element. :param encrypted_data: The encrypted data. :type: lxml.etree.Element | DOMElement | basestring :param key: The key. :type: string :param debug: Activate the xmlsec debug :type: bool :param inplace: update passed data with decrypted result :type: bool :returns: The decrypted element. :rtype: lxml.etree.Element """ if isinstance(encrypted_data, Element): encrypted_data = fromstring(str(encrypted_data.toxml()), forbid_dtd=True) elif isinstance(encrypted_data, basestring): encrypted_data = fromstring(str(encrypted_data), forbid_dtd=True) elif not inplace and isinstance(encrypted_data, etree._Element): encrypted_data = deepcopy(encrypted_data) error_callback_method = None if debug: error_callback_method = print_xmlsec_errors xmlsec.set_error_callback(error_callback_method) mngr = xmlsec.KeysMngr() key = xmlsec.Key.loadMemory(key, xmlsec.KeyDataFormatPem, None) mngr.addKey(key) enc_ctx = xmlsec.EncCtx(mngr) return enc_ctx.decrypt(encrypted_data)
def get_nameid_data(request, key=None): """ Gets the NameID Data of the the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :param key: The SP key :type key: string :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier) :rtype: dict """ if isinstance(request, etree._Element): elem = request else: if isinstance(request, Document): request = request.toxml() elem = fromstring(request, forbid_dtd=True) name_id = None encrypted_entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID') if len(encrypted_entries) == 1: if key is None: raise OneLogin_Saml2_Error( 'Private Key is required in order to decrypt the NameID, check settings', OneLogin_Saml2_Error.PRIVATE_KEY_NOT_FOUND ) encrypted_data_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData') if len(encrypted_data_nodes) == 1: encrypted_data = encrypted_data_nodes[0] name_id = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key) else: entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:NameID') if len(entries) == 1: name_id = entries[0] if name_id is None: raise OneLogin_Saml2_ValidationError( 'NameID not found in the Logout Request', OneLogin_Saml2_ValidationError.NO_NAMEID ) name_id_data = { 'Value': OneLogin_Saml2_Utils.element_text(name_id) } for attr in ['Format', 'SPNameQualifier', 'NameQualifier']: if attr in name_id.attrib.keys(): name_id_data[attr] = name_id.attrib[attr] return name_id_data
def get_id(request): """ Returns the ID of the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :return: string ID :rtype: str object """ if isinstance(request, etree._Element): elem = request else: if isinstance(request, Document): request = request.toxml() elem = fromstring(request) return elem.get('ID', None)
def configs(self, xml): root = lxml.fromstring(xml) pools = self.get_pool_config(xml, root) lds, used_ldns = self.get_ld_config(xml, root, pools) iscsi_ldsets = self.get_iscsi_ldset_config(xml, root) fc_ldsets = self.get_fc_ldset_config(xml, root) hostports = self.get_hostport_config(xml, root) diskarray_max_ld_count = self.get_diskarray_max_ld_count(xml, root) self.set_backend_max_ld_count(xml, root) ldsets = {} ldsets.update(iscsi_ldsets) ldsets.update(fc_ldsets) return pools, lds, ldsets, used_ldns, hostports, diskarray_max_ld_count
def send_cmd(self, cmd, **kwargs): """Send command to VPSA Controller.""" self.ensure_connection(cmd) (method, url, body) = self._generate_vpsa_cmd(cmd, **kwargs) LOG.debug('Invoking %(cmd)s using %(method)s request.', {'cmd': cmd, 'method': method}) host = self.conf.zadara_vpsa_host port = int(self.conf.zadara_vpsa_port) protocol = "https" if self.conf.zadara_vpsa_use_ssl else "http" if protocol == "https": if not self.conf.zadara_ssl_cert_verify: verify = False else: cert = ((self.conf.driver_ssl_cert_path) or None) verify = cert if cert else True else: verify = False if port: api_url = "%s://%s:%d%s" % (protocol, host, port, url) else: api_url = "%s://%s%s" % (protocol, host, url) try: response = requests.request(method, api_url, data=body, verify=verify) except requests.exceptions.RequestException as e: message = (_('Exception: %s') % six.text_type(e)) raise exception.VolumeDriverException(message=message) if response.status_code != 200: raise exception.BadHTTPResponseStatus(status=response.status_code) data = response.content xml_tree = lxml.fromstring(data) status = xml_tree.findtext('status') if status != '0': raise exception.FailedCmdWithDump(status=status, data=data) if method in ['POST', 'DELETE']: LOG.debug('Operation completed with status code %(status)s', {'status': status}) return xml_tree
def test_pretty_print_with_dict_str(self): xml_str = '<test><this><with id="a">and text</with></this></test>' no_xml = "</test>" elem = secET.fromstring(xml_str) expected_xml_string = ("<test>\n" " <this>\n" ' <with id="a">and text</with>\n' " </this>\n" "</test>\n" "</test>\n") stringio = StringIO() pretty_print([elem, no_xml], file=stringio) xml_string = stringio.getvalue() self.assertEqual(xml_string, expected_xml_string)
def testProgress(self): daemon = DummyWrapper([]) response = secET.fromstring( daemon.handle_command('<start_scan parallel="2">' '<scanner_params />' '<targets><target>' '<hosts>localhost1</hosts>' '<ports>22</ports>' '</target><target>' '<hosts>localhost2</hosts>' '<ports>22</ports>' '</target></targets>' '</start_scan>')) scan_id = response.findtext('id') daemon.set_scan_target_progress(scan_id, 'localhost1', 75) daemon.set_scan_target_progress(scan_id, 'localhost2', 25) self.assertEqual(daemon.calculate_progress(scan_id), 50)
def get_issuer(request): """ Gets the Issuer of the Logout Request Message :param request: Logout Request Message :type request: string|DOMDocument :return: The Issuer :rtype: string """ if isinstance(request, Document): request = request.toxml() dom = fromstring(request) issuer = None issuer_nodes = OneLogin_Saml2_Utils.query(dom, '/samlp:LogoutRequest/saml:Issuer') if len(issuer_nodes) == 1: issuer = issuer_nodes[0].text return issuer
def get_session_indexes(request): """ Gets the SessionIndexes from the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :return: The SessionIndex value :rtype: list """ if isinstance(request, Document): request = request.toxml() dom = fromstring(request) session_indexes = [] session_index_nodes = OneLogin_Saml2_Utils.query(dom, '/samlp:LogoutRequest/samlp:SessionIndex') for session_index_node in session_index_nodes: session_indexes.append(session_index_node.text) return session_indexes
def generate_metadata_xml(self): """Helper method to generate the SP metadata XML. Extends the base class metadata generation with extensions, elements and attributes required by the Suomi.fi IdP. Returns (metadata XML string, list of errors) """ metadata, errors = super().generate_metadata_xml() metadata_xml = fromstring(metadata) self._amend_services(metadata_xml) self._amend_contacts(metadata_xml) self._add_entity_attributes_extension(metadata_xml) self._add_ui_info_extension(metadata_xml) metadata = tostring(metadata_xml, encoding='utf-8', xml_declaration=True) return metadata, errors
def get_name_id_data(request, key=None): """ Gets the NameID Data of the the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :param key: The SP key :type key: string :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier) :rtype: dict """ if isinstance(request, Document): request = request.toxml() doc = fromstring(request) name_id = None encrypted_entries = OneLogin_Saml2_Utils.query( doc, '/samlp:LogoutRequest/saml:EncryptedID') if len(encrypted_entries) == 1: if key is None: raise Exception( 'Key is required in order to decrypt the NameID') encrypted_data_nodes = OneLogin_Saml2_Utils.query( doc, '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData') if len(encrypted_data_nodes) == 1: encrypted_data = encrypted_data_nodes[0] name_id = OneLogin_Saml2_Utils.decrypt_element( encrypted_data, key) else: entries = OneLogin_Saml2_Utils.query( doc, '/samlp:LogoutRequest/saml:NameID') if len(entries) == 1: name_id = entries[0] if name_id is None: raise Exception('Not NameID found in the Logout Request') name_id_data = {'Value': name_id.text} for attr in ['Format', 'SPNameQualifier', 'NameQualifier']: if attr in name_id.attrib.keys(): name_id_data[attr] = name_id.attrib[attr] return name_id_data
def get_issuer(request): """ Gets the Issuer of the Logout Request Message :param request: Logout Request Message :type request: string|DOMDocument :return: The Issuer :rtype: string """ if isinstance(request, Document): request = request.toxml() dom = fromstring(request) issuer = None issuer_nodes = OneLogin_Saml2_Utils.query( dom, '/samlp:LogoutRequest/saml:Issuer') if len(issuer_nodes) == 1: issuer = issuer_nodes[0].text return issuer
def test_get_vts_vts_with_mtime(self): daemon = DummyWrapper([]) daemon.add_vt( '1.2.3.4', 'A vulnerability test', vt_params="a", vt_modification_time='02-01-1900', ) response = secET.fromstring( daemon.handle_command('<get_vts vt_id="1.2.3.4"></get_vts>') ) modification_time = response.findall('vts/vt/modification_time') self.assertEqual( '<modification_time>02-01-1900</modification_time>', ET.tostring(modification_time[0]).decode('utf-8'), )
def test_get_vts_vts_with_solution(self): daemon = DummyWrapper([]) daemon.add_vt( '1.2.3.4', 'A vulnerability test', vt_params="a", custom="b", solution="c", solution_t="d", solution_m="e", ) response = secET.fromstring( daemon.handle_command('<get_vts vt_id="1.2.3.4"></get_vts>') ) solution = response.findall('vts/vt/solution') self.assertEqual(1, len(solution))
def get_user(content): """Return LoginGovPlUser instance based on ArtifactResponse. Args: content (str): decoded cipher value Returns: LoginGovPlUser: user object """ tree = fromstring(content) first_name = tree.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue[@{http://www.w3.org/2001/XMLSchema-instance}type="naturalperson:CurrentGivenNameType"]').text last_name = tree.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue[@{http://www.w3.org/2001/XMLSchema-instance}type="naturalperson:CurrentFamilyNameType"]').text date_of_birth = tree.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue[@{http://www.w3.org/2001/XMLSchema-instance}type="naturalperson:DateOfBirthType"]').text pesel = tree.find('.//{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue[@{http://www.w3.org/2001/XMLSchema-instance}type="naturalperson:PersonIdentifierType"]').text return LoginGovPlUser(first_name, last_name, date_of_birth, pesel)
def get_session_indexes(request): """ Gets the SessionIndexes from the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :return: The SessionIndex value :rtype: list """ if isinstance(request, Document): request = request.toxml() dom = fromstring(request) session_indexes = [] session_index_nodes = OneLogin_Saml2_Utils.query( dom, '/samlp:LogoutRequest/samlp:SessionIndex') for session_index_node in session_index_nodes: session_indexes.append(session_index_node.text) return session_indexes
def testGetScanPop(self): daemon = DummyWrapper([ Result('host-detail', value='Some Host Detail'), ]) response = secET.fromstring( daemon.handle_command( '<start_scan target="localhost" ports="80, 443">' '<scanner_params /></start_scan>')) scan_id = response.findtext('id') time.sleep(1) response = secET.fromstring( daemon.handle_command('<get_scans scan_id="%s"/>' % scan_id)) self.assertEqual(response.findtext('scan/results/result'), 'Some Host Detail') response = secET.fromstring( daemon.handle_command('<get_scans details="0" pop_results="1"/>')) self.assertEqual(response.findtext('scan/results/result'), None) response = secET.fromstring( daemon.handle_command('<get_scans scan_id="%s" pop_results="1"/>' % scan_id)) self.assertEqual(response.findtext('scan/results/result'), 'Some Host Detail') response = secET.fromstring( daemon.handle_command('<get_scans scan_id="%s" pop_results="1"/>' % scan_id)) self.assertNotEqual(response.findtext('scan/results/result'), 'Some Host Detail') self.assertEqual(response.findtext('scan/results/result'), None) while True: response = secET.fromstring( daemon.handle_command('<get_scans scan_id="%s" details="0"/>' % scan_id)) scans = response.findall('scan') self.assertEqual(1, len(scans)) scan = scans[0] if int(scan.get('progress')) == 100: break response = secET.fromstring( daemon.handle_command('<delete_scan scan_id="%s" />' % scan_id)) self.assertEqual(response.get('status'), '200')
def login(self): if self.type == 'geonetwork': url = "%sgeonetwork/srv/en/xml.user.login" % self.base headers = { "Content-Type": "application/x-www-form-urlencoded", "Accept": "text/plain" } post = urlencode({ "username": self.user, "password": self.password }) request = Request(url, post, headers) self.opener = build_opener(HTTPCookieProcessor(), HTTPRedirectHandler()) response = self.opener.open(request) doc = dlxml.fromstring(response.read()) assert doc.tag == 'ok', "GeoNetwork login failed!" self.connected = True
def process_error(self, response): doc = fromstring(response) fault_node = doc.find( 'soap-env:Body/soap-env:Fault', namespaces=self.nsmap) if fault_node is None: raise Fault('Unknown fault occured') def get_text(name): child = fault_node.find(name) if child is not None: return child.text raise Fault( message=get_text('faultstring'), code=get_text('faultcode'), actor=get_text('faultactor'), detail=fault_node.find('detail'))
def __init__(self, url): try: response = requests.get(url, stream=True) except requests.ConnectionError as error: print(error) sys.exit(1) try: etree = lxml.fromstring(response.content) except XMLSyntaxError as error: print(error) sys.exit(1) self.nsmap = etree.nsmap self.namespace = get_ns(etree.nsmap, None) self.updated = get_updated(etree, self.nsmap) self.title = get_title(etree, self.namespace) self.items = get_items(etree, self.namespace) self.etree = etree
def pretty_print(xml, file: IOBase = sys.stdout): """Prints beautiful XML-Code This function gets a string containing the xml, an object of List[lxml.etree.Element] or directly a lxml element. Print it with good readable format. Arguments: xml (str, List[lxml.etree.Element] or lxml.etree.Element): xml as string, List[lxml.etree.Element] or directly a lxml element. file: A IOBase type. Can be a File, StringIO, ... """ if not isinstance(file, IOBase): raise TypeError( 'Type needs to be from IOBase, not {}.'.format(type(file)) ) from None if isinstance(xml, list): for item in xml: if etree.iselement(item): file.write( etree.tostring(item, pretty_print=True).decode( sys.getdefaultencoding() + '\n' ) ) else: file.write(item + '\n') elif etree.iselement(xml): file.write( etree.tostring(xml, pretty_print=True).decode( sys.getdefaultencoding() + '\n' ) ) elif isinstance(xml, str): tree = secET.fromstring(xml) file.write( etree.tostring(tree, pretty_print=True).decode( sys.getdefaultencoding() + '\n' ) )
def get_nameid_data(request, key=None): """ Gets the NameID Data of the the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :param key: The SP key :type key: string :return: Name ID Data (Value, Format, NameQualifier, SPNameQualifier) :rtype: dict """ if isinstance(request, etree._Element): elem = request else: if isinstance(request, Document): request = request.toxml() elem = fromstring(request) name_id = None encrypted_entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID') if len(encrypted_entries) == 1: if key is None: raise Exception('Key is required in order to decrypt the NameID') encrypted_data_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:EncryptedID/xenc:EncryptedData') if len(encrypted_data_nodes) == 1: encrypted_data = encrypted_data_nodes[0] name_id = OneLogin_Saml2_Utils.decrypt_element(encrypted_data, key) else: entries = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:NameID') if len(entries) == 1: name_id = entries[0] if name_id is None: raise Exception('Not NameID found in the Logout Request') name_id_data = { 'Value': name_id.text } for attr in ['Format', 'SPNameQualifier', 'NameQualifier']: if attr in name_id.attrib.keys(): name_id_data[attr] = name_id.attrib[attr] return name_id_data
def extractSigData(data): """ Taken from signxml's XMLVerifier, and slightly modified to provide what's needed :param data: SOAP envelope with signature and signed info :return: signedinfo, signature tuple """ require_x509 = True x509_cert = None hmac_key = None validate_schema = True parser = None id_attribute = None ver = XMLVerifier() ver.hmac_key = hmac_key ver.require_x509 = require_x509 ver.x509_cert = x509_cert ver._parser = parser if x509_cert: XMLVerifier.require_x509 = True if id_attribute is not None: ver.id_attributes = (id_attribute, ) root = ver.get_root(data) if root.tag == signxml.ds_tag("Signature"): signature_ref = root else: signature_ref = ver._find(root, "Signature", anywhere=True) # HACK: deep copy won't keep root's namespaces signature = fromstring(etree.tostring(signature_ref), parser=parser) if validate_schema: ver.schema().assertValid(signature) signed_info = ver._find(signature, "SignedInfo") c14n_method = ver._find(signed_info, "CanonicalizationMethod") c14n_algorithm = c14n_method.get("Algorithm") signature_value = ver._find(signature, "SignatureValue") raw_signature = base64.b64decode(signature_value.text) signed_info_c14n = ver._c14n(signed_info, algorithm=c14n_algorithm) return signed_info_c14n, raw_signature
def validate_xml(xml, schema, debug=False): """ Validates a xml against a schema :param xml: The xml that will be validated :type: string|DomDocument :param schema: The schema :type: string :param debug: If debug is active, the parse-errors will be showed :type: bool :returns: Error code or the DomDocument of the xml :rtype: string """ assert isinstance(xml, basestring) or isinstance( xml, Document) or isinstance(xml, etree._Element) assert isinstance(schema, basestring) if isinstance(xml, Document): xml = xml.toxml() elif isinstance(xml, etree._Element): xml = tostring(xml, encoding='unicode') # Switch to lxml for schema validation try: dom = fromstring(xml.encode('utf-8')) except Exception: return 'unloaded_xml' schema_file = join(dirname(__file__), 'schemas', schema) f_schema = open(schema_file, 'r') schema_doc = etree.parse(f_schema) f_schema.close() xmlschema = etree.XMLSchema(schema_doc) if not xmlschema.validate(dom): if debug: stderr.write('Errors validating the metadata') stderr.write(':\n\n') for error in xmlschema.error_log: stderr.write('%s\n' % error.message) return 'invalid_xml' return parseString( etree.tostring(dom, encoding='unicode').encode('utf-8'))
def get_oem_parameter(self): product = os.path.join(os.path.dirname(__file__), 'product.xml') try: with open(product, 'r') as f: xml = f.read() root = lxml.fromstring(xml) vendor_name = root.xpath('./VendorName')[0].text product_dict = {} product_map = root.xpath('./ProductMap/Product') for s in product_map: product_dict[s.attrib['Name']] = int(s.text, 10) return vendor_name, product_dict except OSError as e: with excutils.save_and_reraise_exception() as ctxt: if e.errno == errno.ENOENT: ctxt.reraise = False raise exception.NotFound(_('%s not found.') % product)
def xpath_selector(selector, html, select_all): """ Returns Xpath match for `selector` within `html`. :param selector: XPath string :param html: Unicode content :param select_all: True to get all matches """ from defusedxml import lxml as dlxml from lxml import etree import re # lxml requires argument to be bytes # see https://github.com/kibitzr/kibitzr/issues/47 encoded = html.encode('utf-8') root = dlxml.fromstring(encoded, parser=etree.HTMLParser()) xpath_results = root.xpath(selector) if not xpath_results: logger.warning('XPath selector not found: %r', selector) return False, html if isinstance(xpath_results, list): if select_all is False: xpath_results = xpath_results[0:1] else: xpath_results = [xpath_results] # Serialize xpath_results # see https://lxml.de/xpathxslt.html#xpath-return-values results = [] for r in xpath_results: # namespace declarations if isinstance(r, tuple): results.append("%s=\"%s\"" % (r[0], r[1])) # an element elif hasattr(r, 'tag'): results.append( re.sub(r'\s+', ' ', dlxml.tostring(r, method='html', encoding='unicode'))) else: results.append(r) return True, u"\n".join(six.text_type(x).strip() for x in results)
def prefix_xsl_line(req, id): # if the layer is in the catalogue, try to get the distribution urls # that cannot be precalculated. resource = None try: resource = get_object_or_404(ResourceBase, pk=id) query = {'id': resource.get_real_instance().id} resource = resolve_object( req, resource.get_real_instance_class(), query, permission='base.view_resourcebase', permission_msg=_("You are not permitted to view this resource")) catalogue = get_catalogue() record = catalogue.get_record(resource.uuid) if record: logger.debug(record.xml) except PermissionDenied: return HttpResponse(_("Not allowed"), status=403) except Exception: logger.debug(traceback.format_exc()) msg = f'Could not connect to catalogue to save information for layer "{str(resource)}"' return HttpResponse(msg, status=404) try: # generate an XML document (GeoNode's default is ISO) if resource.metadata_uploaded and resource.metadata_uploaded_preserve: md_doc = etree.tostring(dlxml.fromstring(resource.metadata_xml)) else: md_doc = catalogue.catalogue.csw_gen_xml( resource, settings.CATALOG_METADATA_TEMPLATE) xml = md_doc except Exception: logger.debug(traceback.format_exc()) return HttpResponse("Resource Metadata not available!") site_url = settings.SITEURL.rstrip('/') if settings.SITEURL.startswith( 'http') else settings.SITEURL xsl_static = getattr(settings, 'CATALOG_METADATA_XSL', '/static/metadataxsl/metadata.xsl') xsl_path = f'{site_url}{xsl_static}' xsl_line = f'<?xml-stylesheet type="text/xsl" href="{xsl_path}"?>' return HttpResponse(xsl_line + xml, content_type="text/xml")
def api_request(params): if params['type'] == 'build_info': payload = {'build_id': params['buildId'], 'app_id': params['appId']} else: payload = {'build_id': params['buildId']} try: r = requests.get(params['url'], params=payload, auth=HTTPBasicAuth(params['username'], params['password'])) r.raise_for_status() except requests.exceptions.HTTPError as err: print(err) sys.exit(1) try: returned_xml = lxml.fromstring(r.content) if not params['schema'].validate(returned_xml): raise ValueError('Schema Validation of ' + params['type'] + ' failed') if returned_xml.tag == 'error': raise ValueError(returned_xml.text) if params['type'] == 'build_info': data = parse_build_info(returned_xml) else: data = parse_detailed_report(returned_xml) except ValueError as e: print(e) sys.exit(1) except XMLSyntaxError: print('XML Syntax Error') sys.exit(1) except AttributeError as e: print('Remote XML return error: ' + str(e)) sys.exit(1) return data
def parse(self, raw_xml: str) -> ServiceProviderMetadata: """Parse raw XML to ServiceProviderMetadata""" root = fromstring(raw_xml.encode()) entity_id = root.attrib["entityID"] sp_sso_descriptors = root.findall(f"{{{NS_SAML_METADATA}}}SPSSODescriptor") if len(sp_sso_descriptors) < 1: raise ValueError("no SPSSODescriptor objects found.") # For now we'll only look at the first descriptor. # Even if multiple descriptors exist, we can only configure one descriptor = sp_sso_descriptors[0] auth_n_request_signed = False if "AuthnRequestsSigned" in descriptor.attrib: auth_n_request_signed = descriptor.attrib["AuthnRequestsSigned"].lower() == "true" assertion_signed = False if "WantAssertionsSigned" in descriptor.attrib: assertion_signed = descriptor.attrib["WantAssertionsSigned"].lower() == "true" acs_services = descriptor.findall(f"{{{NS_SAML_METADATA}}}AssertionConsumerService") if len(acs_services) < 1: raise ValueError("No AssertionConsumerService found.") acs_service = acs_services[0] acs_binding = { SAML_BINDING_REDIRECT: SAMLBindings.REDIRECT, SAML_BINDING_POST: SAMLBindings.POST, }[acs_service.attrib["Binding"]] acs_location = acs_service.attrib["Location"] signing_keypair = self.get_signing_cert(root) if signing_keypair: self.check_signature(root, signing_keypair) return ServiceProviderMetadata( entity_id=entity_id, acs_binding=acs_binding, acs_location=acs_location, auth_n_request_signed=auth_n_request_signed, assertion_signed=assertion_signed, signing_keypair=signing_keypair, )
def validate_xml(xml, schema, debug=False): """ Validates a xml against a schema :param xml: The xml that will be validated :type: string|DomDocument :param schema: The schema :type: string :param debug: If debug is active, the parse-errors will be showed :type: bool :returns: Error code or the DomDocument of the xml :rtype: string """ assert isinstance(xml, basestring) or isinstance(xml, Document) or isinstance(xml, etree._Element) assert isinstance(schema, basestring) if isinstance(xml, Document): xml = xml.toxml() elif isinstance(xml, etree._Element): xml = tostring(xml) # Switch to lxml for schema validation try: dom = fromstring(str(xml)) except Exception: return 'unloaded_xml' schema_file = join(dirname(__file__), 'schemas', schema) f_schema = open(schema_file, 'r') schema_doc = etree.parse(f_schema) f_schema.close() xmlschema = etree.XMLSchema(schema_doc) if not xmlschema.validate(dom): if debug: stderr.write('Errors validating the metadata') stderr.write(':\n\n') for error in xmlschema.error_log: stderr.write('%s\n' % error.message) return 'invalid_xml' return parseString(etree.tostring(dom))
def testGetVTs_VTs_with_params(self): daemon = DummyWrapper([]) daemon.add_vt('1.2.3.4', 'A vulnerability test', vt_params="a", custom="b") response = secET.fromstring( daemon.handle_command('<get_vts vt_id="1.2.3.4"></get_vts>')) # The status of the response must be success (i.e. 200) self.assertEqual(response.get('status'), '200') # The response root element must have the correct name self.assertEqual(response.tag, 'get_vts_response') # The response must contain a 'scanner_params' element self.assertIsNotNone(response.find('vts')) vt_params = response[0][0].findall('vt_params') self.assertEqual(1, len(vt_params)) custom = response[0][0].findall('custom') self.assertEqual(1, len(custom)) params = response.findall('vts/vt/vt_params/vt_param') self.assertEqual(2, len(params))
def get_record(self, uuid): results = self._csw_local_dispatch(identifier=uuid) if len(results) < 1: return None result = dlxml.fromstring(results).find('{http://www.isotc211.org/2005/gmd}MD_Metadata') if result is None: return None record = MD_Metadata(result) record.keywords = [] if hasattr(record, 'identification') and hasattr(record.identification, 'keywords'): for kw in record.identification.keywords: record.keywords.extend(kw['keywords']) record.links = {} record.links['metadata'] = self.catalogue.urls_for_uuid(uuid) record.links['download'] = self.catalogue.extract_links(record) return record
def search_records(self, keywords, start, limit, bbox): with self.catalogue: lresults = self._csw_local_dispatch(keywords, keywords, start + 1, limit, bbox) # serialize XML e = dlxml.fromstring(lresults) self.catalogue.records = \ [MD_Metadata(x) for x in e.findall('//{http://www.isotc211.org/2005/gmd}MD_Metadata')] # build results into JSON for API results = [self.catalogue.metadatarecord2dict(doc) for v, doc in self.catalogue.records.iteritems()] result = {'rows': results, 'total': e.find('{http://www.opengis.net/cat/csw/2.0.2}SearchResults').attrib.get( 'numberOfRecordsMatched'), 'next_page': e.find('{http://www.opengis.net/cat/csw/2.0.2}SearchResults').attrib.get( 'nextRecord') } return result
def test_pretty_print_with_dict(self): xml_str = '<test><this><with id="a">and text</with></this></test>' elem = secET.fromstring(xml_str) expected_xml_string = ('<test>\n' ' <this>\n' ' <with id="a">and text</with>\n' ' </this>\n' '</test>\n' '<test>\n' ' <this>\n' ' <with id="a">and text</with>\n' ' </this>\n' '</test>\n') stringio = StringIO() pretty_print([elem, elem], file=stringio) xml_string = stringio.getvalue() self.assertEqual(xml_string, expected_xml_string)
def get_issuer(request): """ Gets the Issuer of the Logout Request Message :param request: Logout Request Message :type request: string|DOMDocument :return: The Issuer :rtype: string """ if isinstance(request, etree._Element): elem = request else: if isinstance(request, Document): request = request.toxml() elem = fromstring(request, forbid_dtd=True) issuer = None issuer_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/saml:Issuer') if len(issuer_nodes) == 1: issuer = OneLogin_Saml2_Utils.element_text(issuer_nodes[0]) return issuer
def get_session_indexes(request): """ Gets the SessionIndexes from the Logout Request :param request: Logout Request Message :type request: string|DOMDocument :return: The SessionIndex value :rtype: list """ if isinstance(request, etree._Element): elem = request else: if isinstance(request, Document): request = request.toxml() elem = fromstring(request, forbid_dtd=True) session_indexes = [] session_index_nodes = OneLogin_Saml2_Utils.query(elem, '/samlp:LogoutRequest/samlp:SessionIndex') for session_index_node in session_index_nodes: session_indexes.append(OneLogin_Saml2_Utils.element_text(session_index_node)) return session_indexes
def test_scan_get_finished_hosts(self): daemon = DummyWrapper([]) response = secET.fromstring( daemon.handle_command('<start_scan>' '<scanner_params /><vts><vt id="1.2.3.4" />' '</vts>' '<targets><target>' '<hosts>192.168.10.20-25</hosts>' '<ports>80,443</ports>' '<finished_hosts>192.168.10.23-24' '</finished_hosts>' '</target>' '<target><hosts>192.168.0.0/24</hosts>' '<ports>22</ports></target>' '</targets>' '</start_scan>')) scan_id = response.findtext('id') time.sleep(1) finished = daemon.get_scan_finished_hosts(scan_id) self.assertEqual(finished, ['192.168.10.23', '192.168.10.24'])
def __init__(self, host_url=None, version='1.2.0', dtd_validation=False, xsd_validation=True): """Create a new XML parser instance containing the geoLink XSD for validation. Args: host_url (str): URL of the OEREBlex host to resolve relative URLs. The complete URL until but without the */api* part has to be set, starting with *http://* or *https://*. version (str): The version of the geoLink schema to be used. Defaults to `1.2.0`. dtd_validation (bool): Enable/disable validation of document type definition (DTD). Optional, defaults to False. xsd_validation (bool): Enable/disable validation against XML schema (XSD). Optional, defaults to True. """ self._host_url = host_url self._version = version self._dtd_validation = dtd_validation self._xsd_validation = xsd_validation xsd = pkg_resources.resource_filename('geolink_formatter', 'schema/v{0}.xsd'.format(version)) with open(xsd) as f: self._schema = XMLSchema(fromstring(f.read()))
def load_metadata(self, url, validate_cert=True): """ Gets the metadata XML from the provided URL :param url: Url where the XML of the Identity Provider Metadata is published. :type url: string :param validate_cert: If the url uses https schema, that flag enables or not the verification of the associated certificate. :type validate_cert: bool :returns: metadata XML :rtype: string """ self._logger.info('Start loading metadata from {0}'.format(self.IN_COMMON_METADATA_SERVICE_URL)) valid = False if validate_cert: response = urllib2.urlopen(url) else: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE response = urllib2.urlopen(url, context=ctx) xml = response.read() if xml: try: dom = fromstring(xml, forbid_dtd=True) sp_descriptor_nodes = OneLogin_Saml2_Utils.query(dom, '//md:SPSSODescriptor') if sp_descriptor_nodes: valid = True except Exception: pass if not valid: raise Exception('Not valid IdP XML found from URL: %s' % url) self._logger.info('Finished loading metadata from {0}'.format(self.IN_COMMON_METADATA_SERVICE_URL)) return xml
def validate_xml(xml, schema, debug=False): # TS: added caching of schema's """ Validates a xml against a schema :param xml: The xml that will be validated :type: string|DomDocument :param schema: The schema :type: string :param debug: If debug is active, the parse-errors will be showed :type: bool :returns: Error code or the DomDocument of the xml :rtype: string """ assert isinstance(xml, basestring) or isinstance( xml, Document) or isinstance(xml, etree._Element) assert isinstance(schema, basestring) if isinstance(xml, Document): xml = xml.toxml() elif isinstance(xml, etree._Element): xml = tostring(xml, encoding='unicode') # Switch to lxml for schema validation try: dom = fromstring(xml.encode('utf-8')) except Exception: return 'unloaded_xml' xmlschema = loadXmlSchemaByFilename(schema) if not xmlschema.validate(dom): if debug: sys.stderr.write('Errors validating the metadata') sys.stderr.write(':\n\n') for error in xmlschema.error_log: sys.stderr.write('%s\n' % error.message) sys.stderr.flush() return 'invalid_xml' return parseString(tostring(dom, encoding='unicode').encode('utf-8'))