Example #1
0
    def parseHTTP(self, client_id, peer, http_header):
        message = HTTP(self.configuration, http_header, peer)

        if not message.parse(self._transparent):
            try:
                version = message.request.version
            except AttributeError:
                version = '1.0'

            if message.reply_string:
                response = Respond.http(
                    client_id,
                    http(
                        str(message.reply_code),
                        '%s<br/>\n<!--\n\n<![CDATA[%s]]>\n\n-->\n' %
                        (message.reply_string, http_header.replace(
                            '\t', '\\t').replace('\r', '\\r').replace(
                                '\n', '\\n\n')), version))
            else:
                response = Respond.http(
                    client_id, http(str(message.reply_code), '', version))

            message = None

        elif message.reply_code:
            response = Respond.http(
                client_id,
                http(str(message.reply_code), self.reply_string,
                     message.request.version))
            message = None

        else:
            response = None

        return message, response
Example #2
0
	def parseHTTP (self, client_id, peer, http_header):
		message = HTTP(self.configuration, http_header, peer)

		if not message.parse(self._transparent):
			try:
				version = message.request.version
			except AttributeError:
				version = '1.0'

			if message.reply_string:
				response = Respond.http(client_id, http(str(message.reply_code), '%s<br/>\n<!--\n\n<![CDATA[%s]]>\n\n-->\n' % (message.reply_string,http_header.replace('\t','\\t').replace('\r','\\r').replace('\n','\\n\n')),version))
			else:
				response = Respond.http(client_id, http(str(message.reply_code),'',version))

			message = None

		elif message.reply_code:
			response = Respond.http(client_id, http(str(message.reply_code), self.reply_string, message.request.version))
			message = None

		else:
			response = None

		return message, response
Example #3
0
	def parseHTTP (self, client_id, peer, http_header):
		message = HTTP(self.configuration, http_header, peer)
		message.parse(self._transparent)
		return message
Example #4
0
            return message, 'http', headers, comment

        # QUICK and DIRTY, let do a intercept using the CONNECT syntax
        if headers.startswith('CONNECT'):
            _ = headers.replace('\r\n', '\n').split('\n\n', 1)
            if _[1] and not _[1].strip():
                headers = _[0]

            elif _[1]:  # is not an empty string
                connect = _[0]
                headers = _[1]
                request = Request(connect.split('\n')[0] + '\n').parse()

                if not request:
                    return message, 'file', 'internal_error.html', ''
                h = HTTP(self.configuration, headers, message.client)
                if not h.parse(self._transparent) or h.reply_code:
                    return message, 'file', 'internal_error.html', ''

                # The trick to not have to extend ICAP
                h.host = request.host
                h.port = request.port
                return h, 'permit', None, comment

        # Parsing the request from the ICAP server
        h = HTTP(self.configuration, headers, message.client)
        if not h.parse(self._transparent) or h.reply_code:
            return message, 'file', 'internal_error.html', comment

        return h, 'permit', None, comment
Example #5
0
	def run (self):
		while self.running:
			try:
				# The timeout is really caused by the SIGALARM sent on the main thread every second
				# BUT ONLY IF the timeout is present in this call
				data = self.request_box.get(timeout=2)
			except Empty:
				if self.enabled:
					if not self.process or self.process.poll() is not None:
						if self.running:
							self.log.error('stopping the worker as the forked process exited !')
						self.running = False
				continue
			except ValueError:
				self.log.error('Problem reading from request_box')
				continue

			try:
				client_id, peer, header, source, tainted = data
			except TypeError:
				self.log.alert('Received invalid message: %s' % data)
				continue

			if self.enabled:
				if not self.process or self.process.poll() is not None:
					if self.running:
						self.log.error('cleanly stopping the worker, as the forked process died on us !')
					self.running = False
					if source != 'nop':
						self.respond(Respond.requeue(client_id, peer, header, source))
					break

			if source == 'nop':
				continue  # /break

			if not self.running:
				self.log.warning('Consumed a message before we knew we should stop.')

			# This code does nothing ATM, as self.stats_timestamp is always null
			stats_timestamp = self.stats_timestamp
			if stats_timestamp:
				# Is this actually atomic as I am guessing?
				# There's a race condition here if not. We're unlikely to hit it though, unless
				# the classifier can take a long time
				self.stats_timestamp = None if stats_timestamp == self.stats_timestamp else self.stats_timestamp

				# we still have work to do after this so don't continue
				stats = self._stats()
				self.respond(Respond.stats(self.wid, stats))

			message = HTTP(self.configuration,header,peer)
			if not message.parse(self._transparent):
				try:
					version = message.request.version
				except AttributeError:
					version = '1.0'
				if message.reply_string:
					self.respond(Respond.http(client_id, http(str(message.reply_code), '%s<br/>\n<!--\n\n<![CDATA[%s]]>\n\n-->\n' % (message.reply_string,header.replace('\t','\\t').replace('\r','\\r').replace('\n','\\n\n')),version)))
				else:
					self.respond(Respond.http(client_id, http(str(message.reply_code),'',version)))
				continue
			if message.reply_code:
				self.respond(Respond.http(client_id, http(str(message.reply_code), self.reply_string, message.request.version)))
				continue

			method = message.request.method

			if source == 'web':
				self.respond(Respond.monitor(client_id, message.request.path))
				continue

			# classify and return the filtered page
			if method in ('GET', 'PUT', 'POST','HEAD','DELETE','PATCH'):
				if not self.enabled:
					self.respond(Respond.download(client_id, message.host, message.port, message.upgrade, message.content_length, self.transparent(message, peer)))
					self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', message.host)
					continue

				(operation, destination), response = self.request(client_id, *(self.classify (message,header,tainted) + (peer, header, source)))
				self.respond(response)
				if operation is not None:
					self.usage.logRequest(client_id, peer, method, message.url, operation, destination)
				continue


			# someone want to use us as https prox, peery
			if method == 'CONNECT':
				# we do allow connect
				if not self.configuration.http.allow_connect or message.port not in self.configuration.security.connect:
					# NOTE: we are always returning an HTTP/1.1 response
					self.respond(Respond.http(client_id, http('501', 'CONNECT NOT ALLOWED\n')))
					self.usage.logRequest(client_id, peer, method, message.url, 'DENY', 'CONNECT NOT ALLOWED')
					pass

				if not self.enabled:
					self.respond(Respond.connect(client_id, message.host, message.port, http))
					continue

				(operation, destination), response = self.connect(client_id, *(self.classify(message,header,tainted)+(peer,header,source)))
				self.respond(response)
				if operation is not None:
					self.usage.logRequest(client_id, peer, method, message.url, operation, destination)
				continue

			if method in ('OPTIONS','TRACE'):
				if message.headers.get('max-forwards',''):
					max_forwards = message.headers.get('max-forwards','Max-Forwards: -1')[-1].split(':')[-1].strip()
					if not max_forwards.isdigit():
						# NOTE: we are always returning an HTTP/1.1 response
						self.respond(Respond.http(client_id, http('400', 'INVALID MAX-FORWARDS\n')))
						self.usage.logRequest(client_id, peer, method, message.url, 'ERROR', 'INVALID MAX FORWARDS')
						continue
					max_forward = int(max_forwards)
					if max_forward < 0 :
						# NOTE: we are always returning an HTTP/1.1 response
						self.respond(Respond.http(client_id, http('400', 'INVALID MAX-FORWARDS\n')))
						self.usage.logRequest(client_id, peer, method, message.url, 'ERROR', 'INVALID MAX FORWARDS')
						continue
					if max_forward == 0:
						if method == 'OPTIONS':
							# NOTE: we are always returning an HTTP/1.1 response
							self.respond(Respond.http(client_id, http('200', '')))
							self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', 'OPTIONS')
							continue
						if method == 'TRACE':
							# NOTE: we are always returning an HTTP/1.1 response
							self.respond(Respond.http(client_id, http('200', header)))
							self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', 'TRACE')
							continue
						raise RuntimeError('should never reach here')
					message.headers.set('max-forwards','Max-Forwards: %d' % (max_forward-1))
				# Carefull, in the case of OPTIONS message.host is NOT message.headerhost
				self.respond(Respond.download(client_id, message.headerhost, message.port, message.upgrade, message.content_length, self.transparent(message, peer)))
				self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', message.headerhost)
				continue

			# WEBDAV
			if method in (
			  'BCOPY', 'BDELETE', 'BMOVE', 'BPROPFIND', 'BPROPPATCH', 'COPY', 'DELETE','LOCK', 'MKCOL', 'MOVE',
			  'NOTIFY', 'POLL', 'PROPFIND', 'PROPPATCH', 'SEARCH', 'SUBSCRIBE', 'UNLOCK', 'UNSUBSCRIBE', 'X-MS-ENUMATTS'):
				self.respond(Respond.download(client_id, message.headerhost, message.port, message.upgrade, message.content_length, self.transparent(message, peer)))
				self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', method)
				continue

			if message.request in self.configuration.http.extensions:
				self.respond(Respond.download(client_id, message.headerhost, message.port, message.upgrade, message.content_length, self.transparent(message, peer)))
				self.usage.logRequest(client_id, peer, method, message.url, 'PERMIT', message.request)
				continue

			# NOTE: we are always returning an HTTP/1.1 response
			self.respond(Respond.http(client_id, http('405', '')))  # METHOD NOT ALLOWED
			self.usage.logRequest(client_id, peer, method, message.url, 'DENY', method)
			continue

		self.respond(Respond.hangup(self.wid))
Example #6
0
			return message, 'file', 'internal_error.html', ''

		if headers.startswith('HTTP/') and (headers.split() + [''])[1].isdigit():
			return message, 'http', headers, comment

		# QUICK and DIRTY, let do a intercept using the CONNECT syntax
		if headers.startswith('CONNECT'):
			_ = headers.replace('\r\n','\n').split('\n\n',1)
			if _[1]:  # is not an empty string
				connect = _[0]
				headers = _[1]
				request = Request(connect.split('\n')[0]).parse()

				if not request:
					return message, 'file', 'internal_error.html', ''
				h = HTTP(self.configuration,headers,message.client)
				if not h.parse(self._transparent) or h.reply_code:
					return message, 'file', 'internal_error.html', ''

				# The trick to not have to extend ICAP
				h.host = request.host
				h.port = request.port
				return h,'permit',None,comment

		# Parsing the request from the ICAP server
		h = HTTP(self.configuration,headers,message.client)
		if not h.parse(self._transparent) or h.reply_code:
			return message, 'file', 'internal_error.html', comment

		return h, 'permit', None, comment
Example #7
0
	def parseHTTP (self, client_id, accept_addr, accept_port, peer, http_header):
		message = HTTP(self.configuration, http_header, peer)
		message.parse(self._transparent)
		return message