def maybe_xml_to_string(message, logger=None): """ Try to parse message as an XML string, and then return it pretty-printed. If message couldn't be parsed, return string representation of it instead. This is used to (debug-)log SAML requests/responses in a readable way. :param message: XML string typically :param logger: logging logger :return: something ready for logging :rtype: string """ if isinstance(message, six.binary_type): # message is returned as binary from pysaml2 in python3 message = message.decode('utf-8') message = str(message) try: from defusedxml import ElementTree as DefusedElementTree parser = DefusedElementTree.DefusedXMLParser() xml = DefusedElementTree.XML(message, parser) return DefusedElementTree.tostring(xml) except Exception as exc: if logger is not None: logger.debug( "Could not parse message of type {!r} as XML: {!r}".format( type(message), exc)) return message
def post(self, request, *args, **kwargs): parser = etree.DefusedXMLParser( # disallow XML with a <!DOCTYPE> processing instruction forbid_dtd=True, # disallow XML with <!ENTITY> declarations inside the DTD forbid_entities=True, # disallow any access to remote or local resources in external entities or DTD forbid_external=True) try: tree = etree.parse(request, parser=parser) query = tree.getroot().find('query').text except (etree.ParseError, ValueError) as e: return JsonResponse({'error': 'XML parse - %s' % e}, status=400) except Exception as e: return JsonResponse({'error': str(e)}, status=400) photos = [] if query and not query.isspace(): photos = [{ 'id': photo.id, 'name': photo.name, 'description': photo.description, 'upload': photo.upload.url, 'owner': photo.owner.username, } for photo in Photo.objects.filter(name__icontains=query, is_public=True)[:100]] return JsonResponse({'photos': photos})
def _kantara_log_assertion_id(self, saml_response, ticket): """ Log the assertion id, which _might_ be required by Kantara. :param saml_response: authn response as a compact XML string :param ticket: Login process state :type saml_response: str | unicode :type ticket: SSOLoginData :return: None """ printed = False try: parser = DefusedElementTree.DefusedXMLParser() xml = DefusedElementTree.XML(str(saml_response), parser) # For debugging, it is very useful to get the full SAML response pretty-printed in the logfile directly self.logger.debug("Created AuthNResponse :\n\n{!s}\n\n".format(DefusedElementTree.tostring(xml))) printed = True attrs = xml.attrib assertion = xml.find('{urn:oasis:names:tc:SAML:2.0:assertion}Assertion') self.logger.info( '{!s}: id={!s}, in_response_to={!s}, assertion_id={!s}'.format( ticket.key, attrs['ID'], attrs['InResponseTo'], assertion.get('ID') ) ) return DefusedElementTree.tostring(xml) except Exception as exc: self.logger.debug("Could not parse message as XML: {!r}".format(exc)) if not printed: # Fall back to logging the whole response self.logger.info("{!s}: authn response: {!s}".format(ticket.key, saml_response))
def parse(self, stream, media_type=None, parser_context=None): parser_context = parser_context or {} encoding = parser_context.get("encoding", settings.DEFAULT_CHARSET) parser = etree.DefusedXMLParser(encoding=encoding) try: return etree.parse(stream, parser=parser, forbid_dtd=True) except (etree.ParseError, ValueError) as exc: raise ParseError("XML parse error - %s" % str(exc))
def parse(self, stream, media_type=None, parser_context=None): """ Parses the incoming bytestream as XML and returns the resulting data. """ parser_context = parser_context or {} encoding = parser_context.get('encoding', 'utf-8') parser = ElementTree.DefusedXMLParser(encoding=encoding) try: tree = ElementTree.parse(stream, parser=parser, forbid_dtd=True) except (ElementTree.ParseError, ValueError) as e: raise ParseError('XML parse error - {}'.format(e)) return tree.getroot()
def parse(self, stream, media_type=None, parser_context=None): """ Parses the incoming bytestream as XML and returns the resulting data. """ parser_context = parser_context or {} encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) parser = etree.DefusedXMLParser(encoding=encoding) try: tree = etree.parse(stream, parser=parser, forbid_dtd=True) except (etree.ParseError, ValueError) as exc: raise ParseError(detail=str(exc)) data = self._xml_convert(tree.getroot()) return data
def insert(self, xml_comment): parser = etree.DefusedXMLParser( # disallow XML with a <!DOCTYPE> processing instruction forbid_dtd=True, # disallow XML with <!ENTITY> declarations inside the DTD forbid_entities=True, # disallow any access to remote or local resources in external entities or DTD forbid_external=True ) try: tree = etree.parse(xml_comment, parser=parser) except (etree.ParseError, ValueError) as e: logger.error('XML parse error - %s' % e) raise e comment = tree.getroot() try: conn = MongoConnection() discussion_id = int(comment.find('discussion_id').text) parent_slug = comment.find('parent_slug') slug = comment.find('slug').text full_slug = comment.find('full_slug').text if parent_slug: parent = conn.db.comments.find_one( {'discussion_id': discussion_id, 'slug': parent_slug.text}) slug = '%s/%s' % (parent['slug'], slug) full_slug = '%s/%s' % (parent['full_slug'], full_slug) is_private = False if comment.find('private') is not None: is_private = bool(comment.find('private').text) conn.db.comments.insert({ 'discussion_id': discussion_id, 'slug': slug, 'full_slug': full_slug, 'posted': datetime.utcnow(), 'author': comment.find('author_info').text, 'text': comment.find('comment_text').text, 'is_private': is_private }) except pymongo.errors.PyMongoError as e: logger.error('Could not save the comment: %s' % e) finally: conn.client.close()