Beispiel #1
0
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
Beispiel #2
0
    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})
Beispiel #3
0
    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))
Beispiel #5
0
 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()
Beispiel #6
0
    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
Beispiel #7
0
    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()