Esempio n. 1
0
    def test_request_version09(self):
        "Test request output for http 0.9"

        request = (b"GET /foo\r\n" b"Hello, how are you?\r\n" b"\r\n")

        req = Requests().parse(request)
        obtained = str(req).split(u'\n')
        should = [(u'******INVALID Requests STREAM <'
                   u' Has invalid Message;>******'), u'-1 Requests-', u'---',
                  u'****INVALID Request < Bad First line in Request;>****',
                  u' [Req. 1st line]']
        if sys.version_info[0] < 3:
            should.append(u'**(raw):GET /foo\r'),
            should.append(u'**'),
        else:
            should.append(u"**(raw):b'GET /foo\\r\\n'**"),

        should.append(u'**INVALID FIRST LINE < Maybe an HTTP/0.9 request;>**')
        should.append(u'[GET]<SP> [/foo] HTTP/[0][.][9] [[CR][LF]]')
        should.append(u' [Req. Headers]')

        should.append(u' [Req. Body] (size 23)')
        if sys.version_info[0] < 3:
            # python2
            should.append(u'Hello, how are you?\r')
            should.append(u'\r')
            should.append(u'')
        else:
            should.append(u"b'Hello, how are you?\\r\\n\\r\\n'"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 2
0
    def test_request_bad_first_line_1(self):
        "Test various bad first lines."

        request = (b"GET\00/foo HTTP/1.1\r\n" b"\r\n")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [(u'******INVALID Requests STREAM <'
                   u' Has invalid Message;>******'), u'-1 Requests-', u'---',
                  u'****INVALID Request < Bad First line in Request;>****',
                  u' [Req. 1st line]']
        if sys.version_info[0] < 3:
            should.append(u'**(raw):GET\x00/foo HTTP/1.1\r'),
            should.append(u'**'),
        else:
            should.append(u"**(raw):b'GET\\x00/foo HTTP/1.1\\r\\n'**"),
        should.append((u'**INVALID FIRST LINE < Bad character detected;'
                       u' Invalid Request method; Maybe an HTTP/0.9 request;'
                       u' Message should be Rejected;>**'))
        should.append((u'[GET<Err><Err><Err><Err><Err>]<SP>'
                       u' [<Err>TTP/1.1] HTTP/[0][.][9] [[CR][LF]]'))
        should.append(u' [Req. Headers]')
        should.append(u' [Req. Body] (size 2)')
        if sys.version_info[0] < 3:
            # python2
            should.append(u'\r')
            should.append(u'')
        else:
            should.append(u"b'\\r\\n'"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 3
0
    def test_regular_request(self):
        "Test regular request output"

        request = (b"GET /foo HTTP/1.0\r\n"
                   b"Host: example.com\r\n"
                   b"Header1: value1\r\n"
                   b"Header2: value2\r\n"
                   b"Content-Length: 18\r\n"
                   b"\r\n"
                   b"This is the body\r\n")

        req = Requests().parse(request)
        obtained = str(req).split(u'\n')
        should = [
            u'-1 Requests-', u'---', u' [Req. 1st line]',
            u'[GET]<SP> [/foo]<SP> HTTP/[1][.][0] [[CR][LF]]',
            u' [Req. Headers]', u'[HOST] [:]<SP> [example.com] [[CR][LF]]',
            u'[HEADER1] [:]<SP> [value1] [[CR][LF]]',
            u'[HEADER2] [:]<SP> [value2] [[CR][LF]]',
            u'[CONTENT-LENGTH] [:]<SP> [18] [[CR][LF]]',
            u' [Req. Body] (size 18)'
        ]
        if sys.version_info[0] < 3:
            # python2
            should.append(u'This is the body\r')
            should.append(u'')
        else:
            should.append(u"b'This is the body\\r\\n'"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 4
0
    def test_request_multiline_headers(self):
        "Test multiline headers output"

        request = (b"GET /foo HTTP/1.0\r\n"
                   b"Host: example.com\r\n"
                   b"H1: v1\r\n"
                   b" H2: v2\r\n"
                   b" H3: v3\r\n"
                   b"foo: bar bar\r\n"
                   b"H4:\r\n"
                   b" H5:v5\r\n"
                   b"\r\n")

        req = Requests().parse(request)
        obtained = str(req).split(u'\n')
        should = [
            u'-1 Requests-', u'---',
            u'****BAD Request < Has invalid Header;>****', u' [Req. 1st line]',
            u'[GET]<SP> [/foo]<SP> HTTP/[1][.][0] [[CR][LF]]',
            u' [Req. Headers]', u'[HOST] [:]<SP> [example.com] [[CR][LF]]',
            u'**BAD HEADER < Optional Multiline Header merged;>**',
            (u'[H1] [:]<SP> [v1<SP>H2:<SP>v2<SP>H3:<SP>v3]'
             u' [[CR][LF]]'), u'[FOO] [:]<SP> [bar<SP>bar] [[CR][LF]]',
            u'**BAD HEADER < Optional Multiline Header merged;>**',
            (u'[H4] [:]<SP> [<SP>H5:v5]'
             u' [[CR][LF]]'), u' [Req. Body] (size 0)'
        ]
        if sys.version_info[0] < 3:
            # python2
            should.append(u'')
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 5
0
class Worker(object):

    request = None
    _sock = None
    _addr = None
    name = u''
    ready = True
    output = b''
    test_id = None
    behavior = None
    default_behavior = None
    test_behavior = None
    keepalive = True
    out_queue = None

    def __init__(self, name, out_queue=None):
        self.config = ConfigFactory.getConfig()
        self.name = name
        self.output = b''
        self.stream = b''
        self.keepalive = True
        self._sock = None
        self._sock_accept_reads = False
        self.out_queue = out_queue
        self.initDefaultBehavior()
        self.setReady()

    def setReady(self):
        self.ready = True
        self.keepalive = True
        self.output = b''
        self.stream = b''
        self.test_id = None
        self.test_behavior = None
        self._sock = None
        self._sock_accept_reads = False

    def initDefaultBehavior(self):
        self.default_behavior = Behavior()
        self.default_behavior.setRegularDefaults()

    def init(self, sock, address):
        self.ready = False
        self._sock = sock
        self._addr = address
        self._sock_accept_reads = True

    def close(self):
        if not self.ready:
            # this will also call setReady()
            self.close_socket()

    def inmsg(self, message):
        inmsg(message,
              prefix=u'BACKEND {0}> '.format(self.name),
              color='blue')

    def outmsg(self, message):
        outmsg(message,
               prefix=u'BACKEND {0}> '.format(self.name),
               color='yellow')

    def setTestId(self, id):
        self.test_id = id

    def setTestBehavior(self, behavior):
        self.test_behavior = behavior

    def getTestBehavior(self):
        if self.test_behavior is not None:
            return self.test_behavior
        else:
            self.default_behavior

    def close_socket_for_read(self):
        """Close the server-client socket for reads incoming from client.

        We do not completly close the socket right now to allow late reads
        in the client side. But this socket will soon be closed.
        """
        if self._sock is not None:
            self.outmsg("Closing socket for reads")
            try:
                self._sock.shutdown(socket.SHUT_RD)
            except Exception:
                # already closed
                pass
        self._sock_accept_reads = False

    def close_socket(self):
        if self._sock is not None:
            self.outmsg("Closing socket")
            try:
                self._sock.shutdown(socket.SHUT_RDWR)
            except Exception:
                # already closed
                pass
            try:
                self._sock.close()
            except:
                pass
            self._sock = None
        self.setReady()

    def write_socket(self):
        if self.output is not None and self.output != b'':
            self.outmsg(self.output)
            self._sock.sendall(self.output)
            self.output = b''
            if not self.keepalive:
                self.close_socket_for_read()

    def read_socket(self):
        if not self._sock_accept_reads:
            # This is for sockets that we decided to cut readings from.
            # like after a 0.9 message
            raw = b''
        else:
            try:
                raw = self._sock.recv(self.config.getint(
                    'BACKEND_SOCK_READ_SIZE'))
            except ConnectionResetError:
                # python3
                raw = b''
            except socket.error as serr:
                # python2 support
                if serr.errno != errno.ECONNRESET:
                    # that's another problem
                    raise
                # [Errno 104] Connection reset by peer
                raw = b''
        self.inmsg(str(raw))
        if b'' == raw:
            # that's a closed socket in fact
            # using select() to catch readable sockets will also catch closed
            # sockets (closed by the client). But theses scokets will now
            # always return an empty string content. You cannot have an empty
            # string content from a readable socket if it is not a closed
            # socket.
            # If you do not close this socket right now, then... you will have
            # it in the readable sockets as vitam aeternam.
            self.close_socket()
        else:
            self.stream += raw
            self.requests = Requests().parse(self.stream)

            # DEBUG
            self.inmsg(str(self.requests))

            if self.requests.count > 0:

                self._load_testid_and_behavior()

                if self.behavior.ignore_content_length:

                    # the current response parsing is maybe wrong.
                    self.requests = Requests()
                    self.requests.parse(self.stream,
                                        compute_content_length=False)
                    self.inmsg('# Stream after removing Content Length.')
                    self.inmsg(str(self.requests))

                if self.requests.count > 0:
                    # Remove from input stream the completed requests
                    self._truncate_input_stream()

                    if self.behavior.echo_query:
                        self.echo_query()

                    # we can send a response, query is fully read
                    self.send_responses()

            else:

                self._load_testid_and_behavior(stream_mode=True)

                if self.behavior.echo_incomplete_query:
                        self.echo_input_stream()

    def _load_testid_and_behavior(self, stream_mode=False):
        if (self.test_id is not None
                and self.detect_test_from_requests(stream_mode)):
            self.behavior = self.getTestBehavior()
        else:
            # this is especially usefull for probe requests
            self.behavior = self.default_behavior

    def _truncate_input_stream(self):
        # self.requests.parsed_idx contains the last index reached with
        # a complete message
        self.stream = self.stream[self.requests.parsed_idx:]

    def echo_query(self):
        if self.out_queue is not None:
            self.outmsg('# echoing queries to thread out_queue')
            self.out_queue.put_nowait(Info(Info.INFO_DATA,
                                           id=self.test_id,
                                           data=self.requests))

    def echo_input_stream(self):
        if self.out_queue is not None:
            self.outmsg('# echoing input stream to thread out_queue')
            self.out_queue.put_nowait(Info(Info.INFO_PARTIAL_DATA,
                                           id=self.test_id,
                                           data=self.stream))

    def detect_test_from_requests(self, stream_mode=False):
        "Check in raw first line of requests for an httpwookiee test marker."
        detected = False
        if stream_mode:
            import six
            block = six.text_type(self.stream)
        else:
            block = self.requests[0].first_line.raw.decode('utf8')

        matches = re.match(r'.*httpw=--(.*)--.*',
                           block,
                           re.S)
        if matches:
            request_test_id = matches.group(1)
            if self.test_id == request_test_id:
                detected = True
        return detected

    def send_responses(self):
        """Prepare the responses stream output.
        """
        position = 1
        if self.requests.valid or self.behavior.accept_invalid_request:
            for request in self.requests:
                self.send_ok(request=request)
                if self.requests.count > 1:
                    # add an allowed extra response separator
                    self.output += b"\r\n"
                position = position + 1
                if (self.behavior.add_wookiee_response and
                        position == self.behavior.wookiee_stream_position):
                    self.send_wookiee()
                    # add an allowed extra response separator
                    self.output += b"\r\n"
                # TODO: behavior timer between wookiee and responses?
        else:
            for request in self.requests:
                if request.valid:
                    self.send_ok(request=request)
                    if self.requests.count > 1:
                        # add an allowed extra response separator
                        self.output += b"\r\n"
                else:
                    # even if asked to keep conn alive on errors, we cannot
                    # keep a conn alive after an http/0.9 request
                    # every incoming data is just crap from 1st query
                    close = ((request.http09)
                             or not(self.behavior.keep_alive_on_error))
                    self.send_400(headers=not(request.http09),
                                  close=close)
                    if close:
                        break
                position = position + 1
                if (self.behavior.add_wookiee_response and
                        position == self.behavior.wookiee_stream_position):
                    self.send_wookiee()
                    # add an allowed extra response separator
                    self.output += b"\r\n"

    def send_ok(self,
                headers=True,
                close=False,
                request=None):
        if request is not None:
            wlocation = self.config.get('BACKEND_WOOKIEE_LOCATION')
            # add support for proxies misconfigured, with no prefix path
            # support : TODO: remove
            prewlocation = '{0}{1}'.format(
                self.config.get('BACKEND_LOCATION_PREFIX'),
                self.config.get('BACKEND_WOOKIEE_LOCATION'))
            if (request.first_line.location == wlocation
                    or request.first_line.location == prewlocation):
                return self.send_wookiee()

        body = b"Hello, World!\r\nIt works!\r\n"
        if self.behavior.alt_content:
            body += self.config.get(
                'SERVER_NON_DEFAULT_LOCATION_CONTENT').encode('utf8')
        else:
            body += self.config.get(
                'SERVER_DEFAULT_LOCATION_CONTENT').encode('utf8')
        if headers:
            self.output += b"HTTP/1.1 200 OK\r\n"
            self.output += b"Content-Length: "
            self.output += str(len(body)).encode('ascii')
            self.output += b"\r\n"
            self.output += b"Content-Type: text/html; charset=utf-8\r\n"
            if close:
                self.output += b"Connection: Close\r\n"
            else:
                self.output += b"Connection: keep-alive\r\n"
            self.output += b"\r\n"
        self.output += body
        if close:
            self.keepalive = False

    def send_400(self, headers=True, close=True):
        if headers:
            self.output += b"HTTP/1.1 400 Bad Request\r\n"
            self.output += b"Content-Type: text/html; charset=utf-8\r\n"
            if close:
                self.output += b"Connection: Close\r\n"
            else:
                self.output += b"Connection: keep-alive\r\n"
            self.output += b"Content-Length: 24\r\n"
            self.output += b"\r\n"
        if close:
            self.keepalive = False
        self.output += b"400, Bad Request. GFY!\r\n"

    def send_wookiee(self, headers=True, close=False):
        wookiee = b"""<html><body>Wookiee !<hr/><pre>
       .             ``.--::-.`          //      //     .      || ||    .   .
                . `-+hdmNNNNNmdys/.     |||. || |||   .        ||//  ||
         .     .:sdNMMMMMMMMMMMMMNdo:`` ||| ||| ||| //]]  //]] || [[   /||]/||]
              :dMMMMMMMMMMMMMNNMNmNho:-:`|||| |||||||  ||||  ||||  [[|||[  |[
     .       +mMMMMMNmNNNMMNydMh+ydo:../o |||  |||  [[//  [[// ||  [[||[[//[[//
           `+MMMMMMMMmyddNdh/No/hdhssys+o+.                .
           oNMMMMMMMMNs/ymdsso-yd/::/yhdds/`                             .
          -NMMMNNNMMNNh-oNmhy:hs:..```.-/ss/.       .      .
         `sMMMMNNhymNNm:+mmd/yd+:--:/oshdys-.
  +      -mMMNNdhdmhyhNs/mmy+mmyyy+shdo/-....
         +MMmddmmNNNmdmdommyyMmho:shs/:-.````.:`        .
         +NMNNdyyysdmmNNmMNdmMm:+dy/:-::-..-../:                        .
    .   `yNNmmdddmdysdmmMMMNMMsody/+/-:/+//.```.-
        :h+:/+syhdmNNmdhmMdNMMmmhsosyddhyo+o/.` .`
       `/+/sddddmdmNNmMNmNh+ymdo/yNMMNhso++`-```                 .
       `/hhmhyhdNMdho+NMmdho/oyhdymMMmy+/:s+.`                 .  .
  .    .sNNNh+smMMMMMMdymNMNms/ohdmdhhyo+ossy:     .             +       .
       .sNNNddmdmNNMMdymMNNhhNmo/oo+/-/hyyhhoo``
       `ohdMMNmso+sNMdNMMMMMMMmyss+--+o::hNNs/.s-                 .
        /ohMMNds-+dmhymmNmNMNho/odmddyyd:omdoy+s-         .
       `::dNNNd+/dNNMNmhNdhdyhhhhhhhNMyhs/y/s+:+.
    .   `/mhdmdshdMNmm++yoooohys+/hmNMoydmo`-s+:`                 .
         smymNdyooNNNNddhddyysys+hmydMy:hho- sm.``/ooo:.
        `hhNNmdo/hmhhmmNmNNmh/ymd+:ohMNyoyy+`sm`- .hNMNs. `-+:-         .
   ``.-:/mdMNmh++dNddddh+hmod+/ohdy/oymNmmdy:oN-s.::sNy--ossho:`..`
`-+hdmNMdNmMmmhoodNshmNmommsyNs//ymmdyohMMMmo+m+Mh:soms/mMMm/`---`+yo.
hNMNmmMMmNdMNmmyyddsshyddhydodmhhso+hmd+mNmyo:hdMm-yNMMNMMNs.:h::sdMNo:
mMmdmMMMNmmdmNhmmhsy+yyhNy+my+Nhhy+:/sNohdshy`ydN+ `sMMMMNNdmmNdNMmhho+/`
MMMMMMMMMmdmhmMNmho::hyhm+:hssm+yNs:/ddshsdoo.yho+./mMMm/-+hNMMMMMMNdoo+o.
MMMMMMMMMNmddyNMd+-.+hsmy-:hohh:mm//shsdoyM+oydsydydmmm- ./-sMMMMMMMMms/oo`
MMMMMMMNMMNymmNmo/:-:+dms:ooshshNs+yh/mhmMNNymmyMMMMMMNo+ho/mMMMMMMMMNms/h:
MMMMMMNMMMddNMNs+/-/ssdmyosodydMdohNsoNNMMMMMy-:dMMMMMMMMMdMMMMMMMNMMMdys+/:
MMMMNmNMMNNNMMMdsosoomNyhdshymNNosNdyyhmMMMMy` -mmhmdmNMMMMMMMMMMNmNMMNmssoo.
MMMMmNMMMNMNMMMNshyoNMMNMNyyNMMNhyMdhNMNMMMdo`:mMMMo` -hMMMMMMMMMMNmMMmmm/:ho
MMMNmMMMMMMMMMMdyNsdNMMMMMNdmMMMmsNMMMMMMMMmmNMNNN+`:.-hMMMMMMMMMMdmNMNdMms/d/
MMMNMMMMMMNMMMMNhdmdMMMMMMMNNNMMNydNMMMMMMMMMMMMmy.s+-hMMMMMMMMMMMmhNMMdNMmyy+`
</pre></html></body>"""
        if headers:
            self.output += b"HTTP/1.1 200 OK\r\n"
            self.output += b"Content-Length: "
            self.output += str(len(wookiee)).encode('ascii')
            self.output += b"\r\n"
            self.output += b"Content-Type: text/html; charset=utf-8\r\n"
            self.output += b"X-Wookiee: True\r\n"
            if close:
                self.output += b"Connection: Close\r\n"
            else:
                self.output += b"Connection: keep-alive\r\n"
            self.output += b"\r\n"
        if close:
            self.keepalive = False

        self.output += wookiee
Esempio n. 6
0
    def read_socket(self):
        if not self._sock_accept_reads:
            # This is for sockets that we decided to cut readings from.
            # like after a 0.9 message
            raw = b''
        else:
            try:
                raw = self._sock.recv(self.config.getint(
                    'BACKEND_SOCK_READ_SIZE'))
            except ConnectionResetError:
                # python3
                raw = b''
            except socket.error as serr:
                # python2 support
                if serr.errno != errno.ECONNRESET:
                    # that's another problem
                    raise
                # [Errno 104] Connection reset by peer
                raw = b''
        self.inmsg(str(raw))
        if b'' == raw:
            # that's a closed socket in fact
            # using select() to catch readable sockets will also catch closed
            # sockets (closed by the client). But theses scokets will now
            # always return an empty string content. You cannot have an empty
            # string content from a readable socket if it is not a closed
            # socket.
            # If you do not close this socket right now, then... you will have
            # it in the readable sockets as vitam aeternam.
            self.close_socket()
        else:
            self.stream += raw
            self.requests = Requests().parse(self.stream)

            # DEBUG
            self.inmsg(str(self.requests))

            if self.requests.count > 0:

                self._load_testid_and_behavior()

                if self.behavior.ignore_content_length:

                    # the current response parsing is maybe wrong.
                    self.requests = Requests()
                    self.requests.parse(self.stream,
                                        compute_content_length=False)
                    self.inmsg('# Stream after removing Content Length.')
                    self.inmsg(str(self.requests))

                if self.requests.count > 0:
                    # Remove from input stream the completed requests
                    self._truncate_input_stream()

                    if self.behavior.echo_query:
                        self.echo_query()

                    # we can send a response, query is fully read
                    self.send_responses()

            else:

                self._load_testid_and_behavior(stream_mode=True)

                if self.behavior.echo_incomplete_query:
                        self.echo_input_stream()
Esempio n. 7
0
    def test_request_bad_chunks(self):
        "Test chunks output"

        request = (b"GET /foo HTTP/1.0\r\n"
                   b"Host: example.com\r\n"
                   b"Transfer-Encoding: chunked\r\n"
                   b"\r\n"
                   b"000000008\r\n"
                   b"12345678\r\n"
                   b"04\r\n"
                   b"abcdefghij\r\n"
                   b"5\r\n"
                   b"abcde\r\n"
                   b"1; ZORG\r\n"
                   b"Z\r\n"
                   b"0\r\n"
                   b"\r\n")

        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        if sys.version_info[0] < 3:
            # python2
            raw8 = (u"**(raw):000000008\\r\\n**"
                    u"**BAD CHUNK < Bad chunk size;>**")
        else:
            raw8 = (u"**(raw):b'000000008\\r\\n'**"
                    u"**BAD CHUNK < Bad chunk size;>**")
        should = [
            u'-1 Requests-', u'---',
            (u'****BAD Request < Has bad Chunk; '
             'Has extra Chunk data;>****'), u' [Req. 1st line]',
            u'[GET]<SP> [/foo]<SP> HTTP/[1][.][0] [[CR][LF]]',
            u' [Req. Headers]', u'[HOST] [:]<SP> [example.com] [[CR][LF]]',
            u'[TRANSFER-ENCODING] [:]<SP> [chunked] [[CR][LF]]',
            u' [Req. Chunks] (5)', raw8, u'[08 (8)] [[CR][LF]]',
            u'[04 (4)] [[CR][LF]]', u'[05 (5)] [[CR][LF]]',
            u'[01 (1)] ;[ ZORG] [[CR][LF]]',
            u'[LAST CHUNK] [0 (0)] [[CR][LF]]', u' [Req. Body] (size 18)'
        ]
        if sys.version_info[0] < 3:
            # python2
            should.append(u'12345678abcdabcdeZ')
        else:
            should.append(u"b'12345678abcdabcdeZ'"),

        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)

        # 2nd set
        request = (b"GET /bar HTTP/1.0\r\n"
                   b"Host: example.com\r\n"
                   b"Transfer-Encoding: chunked\r\n"
                   b"\r\n"
                   b" 8\r\n"
                   b"12345678\r\n"
                   b"0004\r\n"
                   b"abcd\r\n"
                   b"6\n"
                   b"abcdef\n"
                   b"0\r\n"
                   b"\r\n")

        if sys.version_info[0] < 3:
            # python2
            raw8 = (u'**(raw): 8\\r\\n**' u'**BAD CHUNK < Bad chunk start;>**')
            raw6 = (u"**(raw):6\\n****BAD CHUNK < "
                    u"Line end is LF and not CRLF;>**")
        else:
            raw8 = (u'**(raw):b\' 8\\r\\n\'**'
                    u'**BAD CHUNK < Bad chunk start;>**')
            raw6 = (u"**(raw):b'6\\n'****BAD CHUNK < "
                    u"Line end is LF and not CRLF;>**")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')
        should = [
            u'-1 Requests-', u'---',
            (u'****BAD Request < Has bad Chunk; '
             u'Has extra Chunk data;>****'), u' [Req. 1st line]',
            u'[GET]<SP> [/bar]<SP> HTTP/[1][.][0] [[CR][LF]]',
            u' [Req. Headers]', u'[HOST] [:]<SP> [example.com] [[CR][LF]]',
            u'[TRANSFER-ENCODING] [:]<SP> [chunked] [[CR][LF]]',
            u' [Req. Chunks] (4)', raw8, u'[08 (8)] [[CR][LF]]',
            u'[04 (4)] [[CR][LF]]', raw6, u'[06 (6)] [[LF]]',
            u'[LAST CHUNK] [0 (0)] [[CR][LF]]', u' [Req. Body] (size 18)'
        ]
        if sys.version_info[0] < 3:
            # python2
            should.append(u'12345678abcdabcdef')
        else:
            should.append(u"b'12345678abcdabcdef'"),

        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 8
0
    def test_request_bad_headers(self):
        "Test some invalid headers analysis and messages"

        request = (b"GET /foo HTTP/1.0\r\n"
                   b" H2: v2\r\n"
                   b" H3: v3\r\n"
                   b"Host: example.com\r\n"
                   b"Header1: value1\r\n"
                   b"\x07Foo: Bar\rB\r\n"
                   b"Foo2: Bar\r\rB\r\n"
                   b": zog1\r\n"
                   b"Zog2 Zog:zog \r\n"
                   b"Zog2b\t\r Zog:zog \r\n"
                   b"Zog2c\t \r  :zog \r\n"
                   b"Zog3 : zog\r\n"
                   b"Zog4: zog \r\n"
                   b"Zog5\t:zog \r\n"
                   b"Zog6:\tzog \r\n"
                   b"Zog7:zog\t\r\n"
                   b"Zo\0g8: zog \r\n"
                   b"Zog9:\0zog\r\n"
                   b"Zog10:zog\0\r\n"
                   b"Zog11:zog\r\r\n"
                   b"Zog12:zog\n"
                   b"\r\n")

        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [(u'******INVALID Requests STREAM '
                   u'< Has invalid Message;>******'), u'-1 Requests-', u'---',
                  (u'****INVALID Request <'
                   u' Has first header in the optional folding format;'
                   u' Has invalid Header;>****'), u' [Req. 1st line]',
                  u'[GET]<SP> [/foo]<SP> HTTP/[1][.][0] [[CR][LF]]',
                  u' [Req. Headers]',
                  u'**BAD HEADER < Optional Multiline Header detected;>**',
                  u'<SP>[] []<SP> [H2:<SP>v2] [[CR][LF]]',
                  u'**BAD HEADER < Optional Multiline Header detected;>**',
                  u'<SP>[] []<SP> [H3:<SP>v3] [[CR][LF]]',
                  u'[HOST] [:]<SP> [example.com] [[CR][LF]]',
                  u'[HEADER1] [:]<SP> [value1] [[CR][LF]]',
                  (u'**INVALID HEADER < Bad space separator;'
                   u' Invalid character in header name;>**'),
                  u'[<Err>FOO] [:]<SP> [Bar<BS>B] [[CR][LF]]',
                  (u'**BAD HEADER < Bad space separator;'
                   u' Multiple CR detected;>**'),
                  u'[FOO2] [:]<SP> [Bar<BS><BS>B] [[CR][LF]]',
                  u'**INVALID HEADER < Empty header name;>**',
                  u'[] [:]<SP> [zog1] [[CR][LF]]',
                  u'**BAD HEADER < Invalid character in header name; '
                  u'Space in header suffix;>**',
                  u'[ZOG2<ErrSP>ZOG] [:] [zog] <SP>[[CR][LF]]',
                  u'**BAD HEADER < Bad space separator; '
                  u'Invalid character in header name; '
                  u'Space in header suffix;>**',
                  u'[ZOG2B<BS><BS><ErrSP>ZOG] [:] [zog] <SP>[[CR][LF]]',
                  u'**INVALID HEADER < Bad space separator; '
                  u'Invalid character in header name; '
                  u'Space before separator; '
                  u'Space in header suffix;>**',
                  u'[ZOG2C] <BS><ErrSP><BS><ErrSP><ErrSP>[:]'
                  u' [zog] <SP>[[CR][LF]]',
                  u'**INVALID HEADER < Invalid character in header name; '
                  u'Space before separator;>**',
                  u'[ZOG3] <ErrSP>[:]<SP> [zog] [[CR][LF]]',
                  u'**BAD HEADER < Space in header suffix;>**',
                  u'[ZOG4] [:]<SP> [zog] <SP>[[CR][LF]]',
                  (u'**INVALID HEADER < Bad space separator;'
                   u' Space before separator; Space in header suffix;>**'),
                  u'[ZOG5] <BS>[:] [zog] <SP>[[CR][LF]]',
                  (u'**BAD HEADER < Bad space separator;'
                   u' Space in header suffix;>**'),
                  u'[ZOG6] [:]<BS> [zog] <SP>[[CR][LF]]',
                  (u'**BAD HEADER < Space in header suffix;>**'),
                  u'[ZOG7] [:] [zog] <SP>[[CR][LF]]',
                  (u'**INVALID HEADER < Invalid character in header name;'
                   u' Space in header suffix;>**'),
                  u'[ZO<Err>G8] [:]<SP> [zog] <SP>[[CR][LF]]',
                  u'[ZOG9] [:] [\x00zog] [[CR][LF]]',
                  u'[ZOG10] [:] [zog\x00] [[CR][LF]]',
                  u'**BAD HEADER < Multiple CR detected;>**',
                  u'[ZOG11] [:] [zog] [[CR][CR][LF]]',
                  u'**BAD HEADER < Line end is LF and not CRLF;>**',
                  u'[ZOG12] [:] [zog] [[LF]]', u' [Req. Body] (size 0)']
        if sys.version_info[0] < 3:
            # python2
            should.append(u'')
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)
Esempio n. 9
0
    def test_request_absolute_first_line(self):
        "Test absolute uris in first lines."

        # regular absolute domain
        request = (b"GET http://example.com/foo HTTP/1.1\r\n" b"\r\n")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [
            u'-1 Requests-', u'---', u' [Req. 1st line]',
            (u'[GET]<SP> <[http://][example.com]>[/foo]<SP> '
             u'HTTP/[1][.][1] [[CR][LF]]'), u' [Req. Headers]',
            u' [Req. Body] (size 0)'
        ]
        if sys.version_info[0] < 3:
            should.append(u''),
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)

        # absolute domain: empty domain (with https)
        request = (b"GET https:// HTTP/1.1\r\n" b"\r\n")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [(u'******INVALID Requests STREAM <'
                   u' Has invalid Message;>******'), u'-1 Requests-', u'---',
                  u'****INVALID Request < Bad First line in Request;>****',
                  u' [Req. 1st line]']
        should.append((u'**INVALID FIRST LINE < Empty domain in absolute uri;'
                       u' Empty location;>**'))
        should.append((u'[GET]<SP> <[https://][<Err>]>[<Err>]<SP> '
                       u'HTTP/[1][.][1] [[CR][LF]]'))
        should.append(u' [Req. Headers]')
        should.append(u' [Req. Body] (size 0)')
        if sys.version_info[0] < 3:
            should.append(u'')
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)

        # absolute domain: empty domain v2, with 0.9
        request = (b"GET http:///\r\n")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [(u'******INVALID Requests STREAM <'
                   u' Has invalid Message;>******'), u'-1 Requests-', u'---',
                  u'****INVALID Request < Bad First line in Request;>****',
                  u' [Req. 1st line]']
        if sys.version_info[0] < 3:
            should.append(u'**(raw):GET http:///\r')
            should.append(u"**")
        else:
            should.append(u"**(raw):b'GET http:///\\r\\n'**")
        should.append((u'**INVALID FIRST LINE < Empty domain in absolute uri;'
                       u' Maybe an HTTP/0.9 request;>**'))
        should.append((u'[GET]<SP> <[http://][<Err>]>[/] '
                       u'HTTP/[0][.][9] [[CR][LF]]'))
        should.append(u' [Req. Headers]')
        should.append(u' [Req. Body] (size 0)')
        if sys.version_info[0] < 3:
            should.append(u'')
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)

        # absolute domain: bad chars
        request = (b"GET http://-example\x0e.com/bar HTTP/1.1\r\n" b"\r\n")
        req = Requests().parse(request)
        obtained = str(req).split(u'\n')

        should = [(u'******INVALID Requests STREAM <'
                   u' Has invalid Message;>******'), u'-1 Requests-', u'---',
                  u'****INVALID Request < Bad First line in Request;>****',
                  u' [Req. 1st line]']
        should.append((u'**INVALID FIRST LINE < Bad character in domain;'
                       u' Message should be Rejected;>**'))
        should.append((u'[GET]<SP> <[http://][<Err>example<Err>.com]>'
                       u'[/bar]<SP> HTTP/[1][.][1] [[CR][LF]]'))
        should.append(u' [Req. Headers]')
        should.append(u' [Req. Body] (size 0)')
        if sys.version_info[0] < 3:
            should.append(u'')
        else:
            should.append(u"b''"),
        should.append(u' ++++++++++++++++++++++++++++++++++++++')
        should.append(u'')
        should.append(u'---')
        self.assertEqual(should, obtained)