예제 #1
0
파일: http.py 프로젝트: CZ-NIC/dionaea
    def handle_io_in(self, data):
        if self.state == STATE_HEADER:
            # End Of Head
            eoh = data.find(b'\r\n\r\n')
            # Start Of Content
            soc = eoh + 4

            if eoh == -1:
                eoh = data.find(b'\n\n')
                soc = eoh + 2
            if eoh == -1:
                return 0

            header = data[0:eoh]
            data = data[soc:]
            self.header = httpreq(header)
            self.header.log_req()
            for n, v in self.header.headers.items():
                detect_shellshock(self, v)

            if self.header.type == b'GET':
                self.handle_GET()
                return len(data)

            elif self.header.type == b'HEAD':
                self.handle_HEAD()
                return len(data)

            elif self.header.type == b'POST':
                if b'content-type' not in self.header.headers and b'content-type' not in self.header.headers:
                    self.handle_POST()
                    return len(data)

                if self.soap_enabled and b"soapaction" in self.header.headers:
                    return self.handle_POST_SOAP(data)

                try:
                    # at least this information are needed for
                    # cgi.FieldStorage() to parse the content
                    self.env = {
                        'REQUEST_METHOD': 'POST',
                        'CONTENT_LENGTH': self.header.headers[b'content-length'].decode("utf-8"),
                        'CONTENT_TYPE': self.header.headers[b'content-type'].decode("utf-8")
                    }
                except:
                    # ignore decode() errors
                    self.handle_POST()
                    return len(data)

                m = re.compile(
                    "multipart/form-data;\s*boundary=(?P<boundary>.*)",
                    re.IGNORECASE
                ).match(self.env['CONTENT_TYPE'])

                if not m:
                    self.handle_POST()
                    return len(data)

                self.state = STATE_POST
                # More on boundaries see:
                # http://www.apps.ietf.org/rfc/rfc2046.html#sec-5.1.1
                self.boundary = bytes("--" + m.group("boundary") + "--\r\n", "utf-8")

                # dump post content to file
                self.fp_tmp = tempfile.NamedTemporaryFile(
                    delete=False,
                    dir=self.download_dir,
                    prefix="http-",
                    suffix=self.download_suffix
                )

                pos = data.find(self.boundary)
                # ending boundary not found
                if pos < 0:
                    self.cur_length = soc
                    return soc

                self.fp_tmp.write(data[:pos])
                self.handle_POST()
                return soc + pos

            elif self.header.type == b'OPTIONS':
                self.handle_OPTIONS()
                return len(data)

            # ToDo
            # elif self.header.type == b'PUT':
            #     self.handle_PUT()

            # method not found
            self.handle_unknown()
            return len(data)

        elif self.state == STATE_POST:
            pos = data.find(self.boundary)
            length = len(data)
            if pos < 0:
                # boundary not found
                l = length - len(self.boundary)
                if l < 0:
                    l = 0
                self.cur_length = self.cur_length + l

                if self.cur_length > self.max_request_size:
                    # Close connection if request is to large.
                    # RFC2616: "The server MAY close the connection to prevent the client from continuing the request."
                    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14
                    x = self.send_error(413)
                    if x:
                        self.copyfile(x)
                    return length
                self.fp_tmp.write(data[:l])
                return l

            # boundary found
            self.fp_tmp.write(data[:pos+len(self.boundary)])
            self.handle_POST()
            return pos + len(self.boundary)

        elif self.state == STATE_PUT:
            logger.debug("putting to me")
        elif self.state == STATE_SENDFILE:
            logger.debug("sending file")
            return 0

        return len(data)
예제 #2
0
    def handle_io_in(self, data):
        if self.state == STATE_HEADER:
            # End Of Head
            eoh = data.find(b'\r\n\r\n')
            # Start Of Content
            soc = eoh + 4

            if eoh == -1:
                eoh = data.find(b'\n\n')
                soc = eoh + 2
            if eoh == -1:
                return 0

            header = data[0:eoh]
            data = data[soc:]
            self.header = httpreq(header)
            self.header.log_req()
            for n, v in self.header.headers.items():
                detect_shellshock(self, v)

            if self.header.type == b'GET':
                self.handle_GET()
                return len(data)

            elif self.header.type == b'HEAD':
                self.handle_HEAD()
                return len(data)

            elif self.header.type == b'POST':
                if b'content-type' not in self.header.headers and b'content-type' not in self.header.headers:
                    self.handle_POST()
                    return len(data)

                try:
                    # at least this information are needed for
                    # cgi.FieldStorage() to parse the content
                    self.env = {
                        'REQUEST_METHOD':
                        'POST',
                        'CONTENT_LENGTH':
                        self.header.headers[b'content-length'].decode("utf-8"),
                        'CONTENT_TYPE':
                        self.header.headers[b'content-type'].decode("utf-8")
                    }
                except:
                    # ignore decode() errors
                    self.handle_POST()
                    return len(data)

                m = re.compile(
                    "multipart/form-data;\s*boundary=(?P<boundary>.*)",
                    re.IGNORECASE).match(self.env['CONTENT_TYPE'])

                if not m:
                    self.handle_POST()
                    return len(data)

                self.state = STATE_POST
                # More on boundaries see:
                # http://www.apps.ietf.org/rfc/rfc2046.html#sec-5.1.1
                self.boundary = bytes("--" + m.group("boundary") + "--\r\n",
                                      "utf-8")

                # dump post content to file
                self.fp_tmp = tempfile.NamedTemporaryFile(
                    delete=False,
                    dir=self.download_dir,
                    prefix="http-",
                    suffix=self.download_suffix)

                pos = data.find(self.boundary)
                # ending boundary not found
                if pos < 0:
                    self.cur_length = soc
                    return soc

                self.fp_tmp.write(data[:pos])
                self.handle_POST()
                return soc + pos

            elif self.header.type == b'OPTIONS':
                self.handle_OPTIONS()
                return len(data)

            # ToDo
            # elif self.header.type == b'PUT':
            #     self.handle_PUT()

            # method not found
            self.handle_unknown()
            return len(data)

        elif self.state == STATE_POST:
            pos = data.find(self.boundary)
            length = len(data)
            if pos < 0:
                # boundary not found
                l = length - len(self.boundary)
                if l < 0:
                    l = 0
                self.cur_length = self.cur_length + l

                if self.cur_length > self.max_request_size:
                    # Close connection if request is to large.
                    # RFC2616: "The server MAY close the connection to prevent the client from continuing the request."
                    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14
                    x = self.send_error(413)
                    if x:
                        self.copyfile(x)
                    return length
                self.fp_tmp.write(data[:l])
                return l

            # boundary found
            self.fp_tmp.write(data[:pos + len(self.boundary)])
            self.handle_POST()
            return pos + len(self.boundary)

        elif self.state == STATE_PUT:
            logger.debug("putting to me")
        elif self.state == STATE_SENDFILE:
            logger.debug("sending file")
            return 0

        return len(data)
예제 #3
0
파일: http.py 프로젝트: jps3/dionaea
    def handle_io_in(self, data):
        if self.state == STATE_HEADER:
            # End Of Head
            end_of_head = data.find(b'\r\n\r\n')
            # Start Of Content
            start_of_content = end_of_head + 4

            if end_of_head == -1:
                end_of_head = data.find(b'\n\n')
                start_of_content = end_of_head + 2
            if end_of_head == -1:
                return 0

            header = data[0:end_of_head]
            data = data[start_of_content:]
            self.header = httpreq(header, self)
            self.header.log_req()
            for _n, v in self.header.headers.items():
                detect_shellshock(self, v)

            if self.header.type == b'GET':
                self.handle_GET()
                return len(data)

            elif self.header.type == b'HEAD':
                self.handle_HEAD()
                return len(data)

            elif self.header.type == b'POST':
                if b'content-type' not in self.header.headers and b'content-type' not in self.header.headers:
                    self.handle_POST()
                    return len(data)

                if self.soap_enabled and b"soapaction" in self.header.headers:
                    return self.handle_POST_SOAP(data)

                try:
                    self.content_length = int(
                        self.header.headers[b'content-length'].decode("utf-8"))
                    self.content_type = self.header.headers[
                        b'content-type'].decode("utf-8")
                except Exception:
                    # ignore decode() errors
                    logger.warning("Ignoring decode errors", exc_info=True)
                    self.handle_POST()
                    return len(data)

                self.state = STATE_POST

                m = re.compile(
                    r"multipart/form-data;\s*boundary=(?P<boundary>.*)",
                    re.IGNORECASE).match(self.content_type)

                if m:
                    # More on boundaries see:
                    # http://www.apps.ietf.org/rfc/rfc2046.html#sec-5.1.1
                    self.boundary = bytes(
                        "--" + m.group("boundary") + "--\r\n", "utf-8")

                # dump post content to file
                self.fp_tmp = tempfile.NamedTemporaryFile(
                    delete=False,
                    dir=self.download_dir,
                    prefix="http-",
                    suffix=self.download_suffix)

                self.cur_length = start_of_content

                if self.boundary:
                    pos = data.find(self.boundary)
                    # ending boundary not found
                    if pos < 0:
                        return start_of_content
                    self.fp_tmp.write(data[:pos])
                    self.handle_POST()
                    return start_of_content + pos

                if len(data) < self.content_length:
                    return start_of_content
                self.fp_tmp.write(data[:self.content_length])

                self.handle_POST()
                return start_of_content + self.content_length

            elif self.header.type == b'OPTIONS':
                self.handle_OPTIONS()
                return len(data)

            # ToDo
            # elif self.header.type == b'PUT':
            #     self.handle_PUT()

            # method not found
            self.handle_unknown()
            return len(data)

        elif self.state == STATE_POST:
            data_length = len(data)
            if self.boundary:
                pos = data.find(self.boundary)

                if pos < 0:
                    # boundary not found
                    length_processed = data_length - len(self.boundary)
                    if length_processed < 0:
                        length_processed = 0
                    self.cur_length = self.cur_length + length_processed

                    if self._check_max_request_size_reached():
                        return data_length
                    self.fp_tmp.write(data[:length_processed])
                    return length_processed

                # boundary found
                self.fp_tmp.write(data[:pos + len(self.boundary)])
                self.handle_POST()
                return pos + len(self.boundary)

            self.cur_length += data_length
            if self._check_max_request_size_reached():
                return data_length
            if self.fp_tmp.tell() + data_length > self.content_length:
                logger.warning(
                    "More data send as specified in the Content-Length header")
                self.fp_tmp.write(data[:self.content_length -
                                       self.fp_tmp.tell()])
                self.handle_POST()
                return data_length

            self.fp_tmp.write(data)
            if self.fp_tmp.tell() == self.content_length:
                self.handle_POST()
            return data_length

        elif self.state == STATE_PUT:
            logger.debug("putting to me")
        elif self.state == STATE_SENDFILE:
            logger.debug("sending file")
            return 0

        return len(data)