Example #1
0
 def send(self, request):
     """Send given request on the socket, support delayed emission."""
     msg = request.getBytesStream()
     msglen = len(msg)
     outmsg('# SENDING ({0}) =====>'.format(msglen))
     # here we use the not-so real format (special bytes are not
     # replaced in str(), only in getBytesStream())
     Tools.print_message(six.text_type(request), cleanup=True)
     try:
         self._socket_send(msg)
     except socket.error as errmsg:
         outmsg('#<====ABORTED COMMUNICATION WHILE'
                ' SENDING {0}\n#{1}'.format(six.text_type(msg), errmsg))
         return
     while request.is_delayed:
         msg = request.getDelayedOutput()
         msglen = len(msg)
         outmsg('# SENDING Delayed ({0}) =====>'.format(msglen))
         # hopefully we do not use strange bytes in delayed chunks for now
         Tools.print_message(six.text_type(msg), cleanup=True)
         try:
             self._socket_send(msg)
         except socket.error as errmsg:
             outmsg('#<====ABORTED COMMUNICATION WHILE'
                    ' SENDING (delayed) '
                    '{0}\r\n#{1}'.format(six.text_type(msg),
                                         errmsg))
             return
Example #2
0
 def send(self, request):
     """Send given request on the socket, support delayed emission."""
     msg = request.getBytesStream()
     msglen = len(msg)
     outmsg('# SENDING ({0}) =====>'.format(msglen))
     # here we use the not-so real format (special bytes are not
     # replaced in str(), only in getBytesStream())
     Tools.print_message(six.text_type(request), cleanup=True)
     try:
         self._socket_send(msg)
     except socket.error as errmsg:
         outmsg('#<====ABORTED COMMUNICATION WHILE'
                ' SENDING {0}\n#{1}'.format(six.text_type(msg), errmsg))
         return
     while request.is_delayed:
         msg = request.getDelayedOutput()
         msglen = len(msg)
         outmsg('# SENDING Delayed ({0}) =====>'.format(msglen))
         # hopefully we do not use strange bytes in delayed chunks for now
         Tools.print_message(six.text_type(msg), cleanup=True)
         try:
             self._socket_send(msg)
         except socket.error as errmsg:
             outmsg('#<====ABORTED COMMUNICATION WHILE'
                    ' SENDING (delayed) '
                    '{0}\r\n#{1}'.format(six.text_type(msg), errmsg))
             return
Example #3
0
 def __str__(self):
     out = ""
     if self.error:
         if not self.valid:
             out = "****INVALID {0} <".format(self.name)
         else:
             out = "****BAD {0} <".format(self.name)
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">****\n"
     out += " [{0} 1st line]\n{1}".format(self.short_name, self.first_line)
     out += " [{0} Headers]\n".format(self.short_name)
     for header in self.headers:
         out += "{0}".format(header)
     if self.chunked:
         out += " [{0} Chunks] ({1})\n".format(self.short_name,
                                               len(self.chunks))
         for chunk in self.chunks:
             out += "{0}".format(chunk)
     bodylen = len(self.body)
     if (bodylen > 1000):
         body = self.body[0:1000] + b'( to be continued...)'
     else:
         body = self.body
     out += " [{0} Body] (size {1})\n{2}".format(self.short_name, bodylen,
                                                 body)
     out += "\n ++++++++++++++++++++++++++++++++++++++\n"
     return out
Example #4
0
 def __str__(self):
     out = ''
     if self.error:
         if self.ERROR_MAYBE_09 in self.errors:
             out += "**(raw):{0}**\n".format(self.raw)
         if not self.valid:
             out += "**INVALID FIRST LINE <"
         else:
             out += "**BAD FIRST LINE <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     out += "{0}[{1}]{2} ".format(self.prefix, self.method, self.method_sep)
     if self.has_absolute_uri:
         out += "<[{0}][{1}]>".format(self.proto, self.domain)
     out += "[{0}]".format(self.location)
     if self.has_args:
         out += "?[{0}]".format(self.query_string)
     out += "{0} HTTP/[{1}][{2}][{3}]".format(
         self.url_sep,
         self.version_major,
         self.version_sep,
         self.version_minor)
     out += " {0}[{1}]\n".format(
         self.suffix,
         self.eof)
     return out
Example #5
0
    def merge_value(self, other_h):
        """merge this header value with another header (multiline headers)

        Long after the end of parsing the header, parsing the next line,
        and ops_fold multiline header was detected. This headers is now coming
        back with this one the be merged as the value part.
        We need to catch errors on the value header and mix it with the current
        one.
        """
        if self.value == u'':
            if other_h.value_prefix != u'':
                self.value_prefix = u'{0}{1}{2}'.format(self.value_prefix,
                                                        self.value_suffix,
                                                        other_h.value_prefix)
                self.value = u'{0}{1}'.format(other_h.value_prefix,
                                              other_h.value)
        else:
            self.value = u'{0}{1}{2}{3}'.format(self.value,
                                                self.value_suffix,
                                                other_h.value_prefix,
                                                other_h.value)
        self.suffix = other_h.value_suffix
        self.eof = other_h.eof
        for error, value in Tools.iteritems(other_h.errors):
            if error != self.ERROR_MULTILINE_OPTIONAL:
                self.setError(error, critical=False)
        self.setError(self.ERROR_WAS_MULTILINE_OPTIONAL, critical=False)
        if not other_h.valid:
            self.valid = False
Example #6
0
 def __str__(self):
     out = ''
     if self.error:
         if sys.version_info[0] < 3:
             # python2
             out += "**(raw):{0}**".format(
                 self.raw.replace('\r', '\\r').replace('\n', '\\n'))
         else:
             out += "**(raw):{0}**".format(self.raw)
         if not self.valid:
             out += "**INVALID CHUNK <"
         else:
             out += "**BAD CHUNK <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     if self.is_last_chunk:
         out += "[LAST CHUNK] "
     if self.size == b'':
         out += '--unkown size--'
     else:
         if self.has_trailer:
             out += "[{0} ({1})] ;[{2}] [{3}]\n".format(
                 self.size,
                 int(self.size, 16),
                 self.trailer,
                 self.eof)
         else:
             out += "[{0} ({1})] [{2}]\n".format(
                 self.size,
                 self.real_size,
                 self.eof)
     return out
Example #7
0
 def __str__(self):
     out = ""
     if self.error:
         if not self.valid:
             out = "****INVALID {0} <".format(self.name)
         else:
             out = "****BAD {0} <".format(self.name)
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">****\n"
     out += " [{0} 1st line]\n{1}".format(self.short_name, self.first_line)
     out += " [{0} Headers]\n".format(self.short_name)
     for header in self.headers:
         out += "{0}".format(header)
     if self.chunked:
         out += " [{0} Chunks] ({1})\n".format(self.short_name,
                                               len(self.chunks))
         for chunk in self.chunks:
             out += "{0}".format(chunk)
     bodylen = len(self.body)
     if (bodylen > 1000):
         body = self.body[0:1000] + b'( to be continued...)'
     else:
         body = self.body
     out += " [{0} Body] (size {1})\n{2}".format(self.short_name,
                                                 bodylen,
                                                 body)
     out += "\n ++++++++++++++++++++++++++++++++++++++\n"
     return out
Example #8
0
    def test_3010_method_separator(self):
        "Test various characters after the METHOD."
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.req.set_method_sep(self.separator)

        # for RP mode:
        self.transmission_map = {
            'GET{0} '.format(self.separator): self.STATUS_TRANSMITTED_CRAP,
            'GET{0}'.format(self.separator): self.STATUS_TRANSMITTED_EXACT,
            'GET ': self.STATUS_TRANSMITTED_CRAP,
        }

        # FIXME: may be an err400 in http 0.9
        # GETXXXfoo HTTP/1.1
        #  method    url       noproto
        # sending err400 in 0.9 is not plainly wrong

        # playing with the method keyword we can expect err 400
        # for every bad character...
        self._add_default_status_map(valid=self.valid_method_suffix,
                                     always_allow_rejected=True)

        # Local adjustments
        self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR

        self._end_1st_line_query()
Example #9
0
    def test_3013_line_prefix(self):
        "Some characters before the query..."
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_MINOR)
        self.req.set_first_line_prefix(self.separator)

        # for RP mode:
        self.transmission_map = {
            '{0}GET'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' GET': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=self.valid_prefix,
            always_allow_rejected=self.can_be_rejected
        )

        # local changes
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR

        self._end_1st_line_query()
Example #10
0
    def test_3010_method_separator(self):
        "Test various characters after the METHOD."
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.req.set_method_sep(self.separator)

        # for RP mode:
        self.transmission_map = {
            'GET{0} '.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            'GET{0}'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            'GET ': self.STATUS_TRANSMITTED_CRAP,
        }

        # FIXME: may be an err400 in http 0.9
        # GETXXXfoo HTTP/1.1
        #  method    url       noproto
        # sending err400 in 0.9 is not plainly wrong

        # playing with the method keyword we can expect err 400
        # for every bad character...
        self._add_default_status_map(valid=self.valid_method_suffix,
                                     always_allow_rejected=True)

        # Local adjustments
        self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR

        self._end_1st_line_query()
Example #11
0
 def __str__(self):
     out = ""
     if not self.valid:
         out = "******INVALID {0} STREAM <".format(self.name)
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">******\n"
     out += "-{0} {1}-".format(self.count, self.name)
     for resp in self.messages:
         out += "\n---\n{0}\n---".format(resp)
     return out
Example #12
0
 def test_3023_crcrcrlf_line_prefix(self):
     self.separator = u'\r\r\r\r\r\n'
     self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                       Tools.show_chars(self.separator))
     self.setGravity(BaseTest.GRAVITY_MINOR)
     self.req.set_first_line_prefix(self.separator)
     # for RP mode:
     self.transmission_map = {
         '{0}GET'.format(self.separator): self.STATUS_TRANSMITTED_EXACT,
         ' GET': self.STATUS_TRANSMITTED_CRAP,
     }
     self._add_default_status_map(valid=True, always_allow_rejected=True)
     self._end_1st_line_query(http09_allowed=False)
Example #13
0
 def __str__(self):
     out = ''
     if self.error:
         if self.ERROR_MAYBE_09 in self.errors:
             out += "**(raw):{0}**".format(self.raw)
         if not not self.valid:
             out += "**INVALID FIRST LINE <"
         else:
             out += "**BAD FIRST LINE <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     out += "HTTP/[{0}][{1}][{2}] [{3}] [{4}] [{5}]\n".format(
         self.version_major, self.version_sep, self.version_minor,
         self.code, self.value, self.eof)
     return out
Example #14
0
 def test_3023_crcrcrlf_line_prefix(self):
     self.separator = u'\r\r\r\r\r\n'
     self.real_test = "{0}_{1}".format(
         inspect.stack()[0][3],
         Tools.show_chars(self.separator))
     self.setGravity(BaseTest.GRAVITY_MINOR)
     self.req.set_first_line_prefix(self.separator)
     # for RP mode:
     self.transmission_map = {
         '{0}GET'.format(
             self.separator): self.STATUS_TRANSMITTED_EXACT,
         ' GET': self.STATUS_TRANSMITTED_CRAP,
     }
     self._add_default_status_map(
         valid=True,
         always_allow_rejected=True)
     self._end_1st_line_query(http09_allowed=False)
Example #15
0
    def test_3014_line_suffix(self):
        "Let's add some garbage after the protocol."
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_WARNING)
        self.req.set_first_line_suffix(self.separator)

        # for RP mode:
        self.transmission_map = {
            ' HTTP/1.0{0}\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1{0}\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1 \r\n': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #16
0
    def _end_1st_line_query(self,
                            responses=None,
                            http09_allowed=False,
                            expected_number=1,
                            status_map=None):
        if responses is None:
            responses = self.send_queries()

        self.analysis(responses,
                      http09_allowed=http09_allowed,
                      regular_expected=False)

        self.adjust_status_by_map(status_map)

        allowed = []
        for status_elt, status_gravity in Tools.iteritems(self.status_map):
            if status_gravity is self.GRAVITY_OK:
                allowed.append(status_elt)
        self.assertIn(self.status, allowed)
Example #17
0
 def __str__(self):
     out = ''
     if self.error:
         if self.ERROR_MAYBE_09 in self.errors:
             out += "**(raw):{0}**".format(self.raw)
         if not not self.valid:
             out += "**INVALID FIRST LINE <"
         else:
             out += "**BAD FIRST LINE <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     out += "HTTP/[{0}][{1}][{2}] [{3}] [{4}] [{5}]\n".format(
         self.version_major,
         self.version_sep,
         self.version_minor,
         self.code,
         self.value,
         self.eof)
     return out
Example #18
0
 def __str__(self):
     out = ''
     if self.error:
         if not self.valid:
             out += "**INVALID HEADER <"
         else:
             out += "**BAD HEADER <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     out += "{0}[{1}] {2}[{3}]{4} [{5}] {6}[{7}]\n".format(
         self.header_prefix,
         self.header,
         self.separator_prefix,
         self.separator,
         self.value_prefix,
         self.value,
         self.value_suffix,
         self.eof)
     return out
Example #19
0
    def test_3016_line_suffix_with_char_H(self):
        "Nginx, for example, likes the H character"
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_WARNING)
        self.req.set_first_line_suffix(self.separator + u'H')

        # for RP mode:
        self.transmission_map = {
            ' HTTP/1.0{0}H\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1{0}H\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            'HTTP/1.1{0}H H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.1 H\r\n': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #20
0
    def _end_1st_line_query(self,
                            responses=None,
                            http09_allowed=False,
                            expected_number=1,
                            status_map=None):
        if responses is None:
            responses = self.send_queries()

        self.analysis(responses,
                      http09_allowed=http09_allowed,
                      regular_expected=False)

        self.adjust_status_by_map(status_map)

        allowed = []
        for status_elt, status_gravity in Tools.iteritems(self.status_map):
            if status_gravity is self.GRAVITY_OK:
                allowed.append(status_elt)
        self.assertIn(self.status,
                      allowed)
Example #21
0
    def test_3014_line_suffix(self):
        "Let's add some garbage after the protocol."
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_WARNING)
        self.req.set_first_line_suffix(self.separator)

        # for RP mode:
        self.transmission_map = {
            ' HTTP/1.0{0}\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1{0}\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1 \r\n': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #22
0
    def test_3017_line_suffix_with_double_HTTP11(self):
        "Ending first line with two times the protocol"
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.req.set_first_line_suffix(self.separator + u'HTTP/1.1')

        # for RP mode:
        self.transmission_map = {
            'HTTP/1.1{0}HTTP/1.1\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            'HTTP/1.0{0}HTTP/1.0\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.0{0}HTTP/1.1\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.1{0}HTTP/1.0\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #23
0
    def _analyze_invalid_echo_queries(self, stream_mode=False):
        "Having a backend received query which is invalid"
        if self.transmission_zone is not None:
            if stream_mode:
                zone = self.backend_queries
            else:
                if self.transmission_zone is Tools.ZONE_FIRST_LINE:
                    query = self.backend_queries[0]
                    zone = query.first_line.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))
                if self.transmission_zone is Tools.ZONE_HEADERS:
                    query = self.backend_queries[0]
                    zone = b''
                    for header in query.headers:
                        zone += header.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))
                if self.transmission_zone is Tools.ZONE_CHUNK_SIZE:
                    query = self.backend_queries[0]
                    zone = b''
                    if query.chunked:
                        for chunk in query.chunks:
                            zone += chunk.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))

        if self.transmission_map:
            for proof, status in Tools.iteritems(self.transmission_map):
                # here we manipulate bytes strings
                if isinstance(proof, six.string_types):
                    # we do not use special non-ascii chars internally
                    proof = proof.encode('ascii')
                if proof in zone:
                    inmsg('# found one transmission proof,'
                          ' status to : {0}'.format(status))
                    inmsg(repr(proof))
                    self.setStatus(status)
                    return True

        self.setStatus(self.STATUS_TRANSMITTED)
Example #24
0
    def test_3011_location_separator(self):
        "After the query string, valid separator or a forbidden char?"
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_CRITICAL)
        self.req.set_location_sep(self.separator)

        # for RP mode:
        self.transmission_map = {
            '{0}HTTP/1.1 H'.format(self.separator):
            self.STATUS_TRANSMITTED,
            ' HTTP/1.1 H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            ' HTTP/1.0 H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            '{0} H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            '{0}HTTP/1.1\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
        }

        # RFC states that some of the separators, like FF, HTAB, VT, CR
        # are allowed, but ... well, .., we should allow rejection on most
        # of theses things (that should not be an error)
        self._add_default_status_map(
            http09_allowed=self.valid_09_location,
            valid=self.valid_location,
            always_allow_rejected=self.can_be_rejected)

        # Local adjustments
        if self.separator in [Tools.BEL, Tools.BS]:
            # better to reject, but this transmission is done the right
            # way if you do not consider theses chars as spaces
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR
            self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        else:
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_WARNING
            self.status_map[
                self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_WARNING

        self._end_1st_line_query(http09_allowed=self.valid_09_location)
Example #25
0
    def _analyze_invalid_echo_queries(self, stream_mode=False):
        "Having a backend received query which is invalid"
        if self.transmission_zone is not None:
            if stream_mode:
                zone = self.backend_queries
            else:
                if self.transmission_zone is Tools.ZONE_FIRST_LINE:
                    query = self.backend_queries[0]
                    zone = query.first_line.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))
                if self.transmission_zone is Tools.ZONE_HEADERS:
                    query = self.backend_queries[0]
                    zone = b''
                    for header in query.headers:
                        zone += header.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))
                if self.transmission_zone is Tools.ZONE_CHUNK_SIZE:
                    query = self.backend_queries[0]
                    zone = b''
                    if query.chunked:
                        for chunk in query.chunks:
                            zone += chunk.raw
                    inmsg('# zone to analyze:.')
                    inmsg(str(zone))

        if self.transmission_map:
            for proof, status in Tools.iteritems(self.transmission_map):
                # here we manipulate bytes strings
                if isinstance(proof, six.string_types):
                    # we do not use special non-ascii chars internally
                    proof = proof.encode('ascii')
                if proof in zone:
                    inmsg('# found one transmission proof,'
                          ' status to : {0}'.format(status))
                    inmsg(repr(proof))
                    self.setStatus(status)
                    return True

        self.setStatus(self.STATUS_TRANSMITTED)
Example #26
0
    def test_3011_location_separator(self):
        "After the query string, valid separator or a forbidden char?"
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_CRITICAL)
        self.req.set_location_sep(self.separator)

        # for RP mode:
        self.transmission_map = {
            '{0}HTTP/1.1 H'.format(
                self.separator): self.STATUS_TRANSMITTED,
            ' HTTP/1.1 H'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            ' HTTP/1.0 H'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            '{0} H'.format(self.separator):  self.STATUS_TRANSMITTED_CRAP,
            '{0}HTTP/1.1\r\n'.format(
                self.separator):  self.STATUS_TRANSMITTED_EXACT,
        }

        # RFC states that some of the separators, like FF, HTAB, VT, CR
        # are allowed, but ... well, .., we should allow rejection on most
        # of theses things (that should not be an error)
        self._add_default_status_map(
            http09_allowed=self.valid_09_location,
            valid=self.valid_location,
            always_allow_rejected=self.can_be_rejected)

        # Local adjustments
        if self.separator in [Tools.BEL, Tools.BS]:
            # better to reject, but this transmission is done the right
            # way if you do not consider theses chars as spaces
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR
            self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        else:
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_WARNING
            self.status_map[
                self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_WARNING

        self._end_1st_line_query(http09_allowed=self.valid_09_location)
Example #27
0
    def test_3018_location_separator_and_extra_proto(self):
        "After the query, valid separator or a forbidden char? Proto repeated."
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_MINOR)
        self.req.add_argument('last', 'marker')
        self.req.set_location_sep(self.separator)
        self.req.set_http_version(major=1, minor=1, force=True)
        self.req.set_first_line_suffix(u' HTTP/1.1')

        # for RP mode:
        self.transmission_map = {
            '{0}HTTP/1.1 H'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1 H'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            ' HTTP/1.0 H'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            'last=marker HTTP/1.0\r\n'.format(
                self.separator):  self.STATUS_TRANSMITTED_CRAP,
            'last=marker HTTP/1.1\r\n'.format(
                self.separator):  self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=self.valid_location)

        # Local adjustments
        if self.separator in [Tools.BEL, Tools.BS]:
            # better to reject, but this transmission is done the right
            # way if you do not consider theses chars as spaces
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR

        # local changes
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_09DOWNGRADE] = self.GRAVITY_CRITICAL
        self.status_map[self.STATUS_09OK] = self.GRAVITY_CRITICAL

        self._end_1st_line_query()
Example #28
0
    def test_3013_line_prefix(self):
        "Some characters before the query..."
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_MINOR)
        self.req.set_first_line_prefix(self.separator)

        # for RP mode:
        self.transmission_map = {
            '{0}GET'.format(self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' GET': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=self.valid_prefix,
            always_allow_rejected=self.can_be_rejected)

        # local changes
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR

        self._end_1st_line_query()
Example #29
0
    def test_3016_line_suffix_with_char_H(self):
        "Nginx, for example, likes the H character"
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_WARNING)
        self.req.set_first_line_suffix(self.separator + u'H')

        # for RP mode:
        self.transmission_map = {
            ' HTTP/1.0{0}H\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1{0}H\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            'HTTP/1.1{0}H H'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.1 H\r\n': self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #30
0
    def test_3017_line_suffix_with_double_HTTP11(self):
        "Ending first line with two times the protocol"
        self.real_test = "{0}_{1}".format(
            inspect.stack()[0][3],
            Tools.show_chars(self.separator))
        self.req.set_first_line_suffix(self.separator + u'HTTP/1.1')

        # for RP mode:
        self.transmission_map = {
            'HTTP/1.1{0}HTTP/1.1\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_EXACT,
            'HTTP/1.0{0}HTTP/1.0\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.0{0}HTTP/1.1\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
            'HTTP/1.1{0}HTTP/1.0\r\n'.format(
                self.separator): self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(
            valid=False)
        self._end_1st_line_query(http09_allowed=False)
Example #31
0
    def test_3018_location_separator_and_extra_proto(self):
        "After the query, valid separator or a forbidden char? Proto repeated."
        self.real_test = "{0}_{1}".format(inspect.stack()[0][3],
                                          Tools.show_chars(self.separator))
        self.setGravity(BaseTest.GRAVITY_MINOR)
        self.req.add_argument('last', 'marker')
        self.req.set_location_sep(self.separator)
        self.req.set_http_version(major=1, minor=1, force=True)
        self.req.set_first_line_suffix(u' HTTP/1.1')

        # for RP mode:
        self.transmission_map = {
            '{0}HTTP/1.1 H'.format(self.separator):
            self.STATUS_TRANSMITTED_EXACT,
            ' HTTP/1.1 H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            ' HTTP/1.0 H'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            'last=marker HTTP/1.0\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
            'last=marker HTTP/1.1\r\n'.format(self.separator):
            self.STATUS_TRANSMITTED_CRAP,
        }

        self._add_default_status_map(valid=self.valid_location)

        # Local adjustments
        if self.separator in [Tools.BEL, Tools.BS]:
            # better to reject, but this transmission is done the right
            # way if you do not consider theses chars as spaces
            self.status_map[self.STATUS_TRANSMITTED] = self.GRAVITY_MINOR

        # local changes
        self.status_map[self.STATUS_TRANSMITTED_EXACT] = self.GRAVITY_MINOR
        self.status_map[self.STATUS_09DOWNGRADE] = self.GRAVITY_CRITICAL
        self.status_map[self.STATUS_09OK] = self.GRAVITY_CRITICAL

        self._end_1st_line_query()
Example #32
0
 def __str__(self):
     out = ''
     if self.error:
         if self.ERROR_MAYBE_09 in self.errors:
             out += "**(raw):{0}**\n".format(self.raw)
         if not self.valid:
             out += "**INVALID FIRST LINE <"
         else:
             out += "**BAD FIRST LINE <"
         for error, value in Tools.iteritems(self.errors):
             out += " {0};".format(error)
         out += ">**\n"
     out += "{0}[{1}]{2} ".format(self.prefix, self.method, self.method_sep)
     if self.has_absolute_uri:
         out += "<[{0}][{1}]>".format(self.proto, self.domain)
     out += "[{0}]".format(self.location)
     if self.has_args:
         out += "?[{0}]".format(self.query_string)
     out += "{0} HTTP/[{1}][{2}][{3}]".format(self.url_sep,
                                              self.version_major,
                                              self.version_sep,
                                              self.version_minor)
     out += " {0}[{1}]\n".format(self.suffix, self.eof)
     return out