def test_run_dnsexception(self): self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query(IgnoreArg(), 'PTR').AndRaise(DNSException) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())
def test_finish(self): self.mox.StubOutWithMock(socket, "gethostbyaddr") socket.gethostbyaddr("127.0.0.1").AndReturn(("example.com", None, None)) self.mox.ReplayAll() ptr = PtrLookup("127.0.0.1") ptr.start() self.assertEqual("example.com", ptr.finish(runtime=1.0))
def test_run_greenletexit(self): self.mox.StubOutWithMock(socket, "gethostbyaddr") socket.gethostbyaddr("127.0.0.1").AndRaise(gevent.GreenletExit) self.mox.ReplayAll() ptr = PtrLookup("abcd") self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())
def test_finish(self): self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query(IgnoreArg(), 'PTR').AndReturn(['example.com']) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') ptr.start() self.assertEqual('example.com', ptr.finish(runtime=1.0))
def test_run_nxdomain(self): self.mox.StubOutWithMock(dns_resolver, 'query') dns_resolver.query(IgnoreArg(), 'PTR').AndRaise(NXDOMAIN) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') assert_is_instance(ptr, gevent.Greenlet) assert_is_none(ptr._run())
def test_run_no_result(self): self.mox.StubOutWithMock(socket, 'gethostbyaddr') socket.gethostbyaddr('127.0.0.1').AndRaise(socket.herror) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())
def test_finish(self): self.mox.StubOutWithMock(socket, 'gethostbyaddr') socket.gethostbyaddr('127.0.0.1').AndReturn( ('example.com', None, None)) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') ptr.start() self.assertEqual('example.com', ptr.finish(runtime=1.0))
def test_finish_timeout(self): self.mox.StubOutWithMock(dns_resolver, 'query') def long_sleep(*args): gevent.sleep(1.0) dns_resolver.query(IgnoreArg(), 'PTR').WithSideEffects(long_sleep) self.mox.ReplayAll() ptr = PtrLookup('127.0.0.1') ptr.start() self.assertIsNone(ptr.finish(runtime=0.0))
def test_finish_timeout(self): def long_sleep(*args): gevent.sleep(1.0) self.mox.StubOutWithMock(socket, "gethostbyaddr") socket.gethostbyaddr("127.0.0.1").WithSideEffects(long_sleep) self.mox.ReplayAll() ptr = PtrLookup("127.0.0.1") ptr.start() self.assertIsNone(ptr.finish(runtime=0.001))
def test_from_getsockname(self): sock = self.mox.CreateMockAnything() sock.getsockname().AndReturn(('127.0.0.1', 0)) self.mox.ReplayAll() ptr, port = PtrLookup.from_getsockname(sock) self.assertEqual(0, port) self.assertIsInstance(ptr, PtrLookup) self.assertEqual('127.0.0.1', ptr.ip)
def __call__(self, environ, start_response): ptr_lookup = PtrLookup(environ.get('REMOTE_ADDR', '0.0.0.0')) ptr_lookup.start() try: self._validate_request(environ) env = self._get_envelope(environ) self._add_envelope_extras(environ, env, ptr_lookup) self._enqueue_envelope(env) except WsgiResponse as res: start_response(res.status, res.headers) return res.data except Exception as exc: logging.log_exception(__name__) msg = '{0!s}\n'.format(exc) content_length = str(len(msg)) headers = [('Content-Length', content_length), ('Content-Type', 'text/plain')] start_response('500 Internal Server Error', headers) return [msg] finally: ptr_lookup.kill(block=False)
def test_run_bad_ip(self): self.mox.ReplayAll() ptr = PtrLookup("abcd") self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())
def test_run_dnssyntaxerror(self): self.mox.StubOutWithMock(dns_resolver, 'query') self.mox.ReplayAll() ptr = PtrLookup('abcd') self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())
class SmtpSession(object): def __init__(self, address, validator_class, handoff): self.extended_smtp = False self.security = None self.address = address self.reverse_address = None self.handoff = handoff self.validators = validator_class(self) if validator_class else None self.envelope = None self.ehlo_as = None self.auth = None self._ptr_lookup = None def _call_validator(self, command, *args): method = 'handle_' + command if hasattr(self.validators, method): getattr(self.validators, method)(*args) @property def protocol(self): proto = 'SMTP' if self.extended_smtp: proto = 'ESMTP' if self.security == 'TLS': proto += 'S' if self.auth: proto += 'A' return proto def BANNER_(self, reply): self._ptr_lookup = PtrLookup(self.address[0]) self._ptr_lookup.start() self._call_validator('banner', reply, self.address) def EHLO(self, reply, ehlo_as): self._call_validator('ehlo', reply, ehlo_as) self.extended_smtp = True if reply.code == '250': self.ehlo_as = ehlo_as self.envelope = None def HELO(self, reply, helo_as): self._call_validator('helo', reply, helo_as) if reply.code == '250': self.ehlo_as = helo_as self.envelope = None def TLSHANDSHAKE(self): self._call_validator('tls') self.security = 'TLS' def AUTH(self, reply, creds): self._call_validator('auth', reply, creds) if reply.code == '235': self.auth = (creds.authcid, creds.authzid) def RSET(self, reply): self.envelope = None def MAIL(self, reply, address, params): self._call_validator('mail', reply, address, params) if reply.code == '250': self.envelope = Envelope(sender=address) def RCPT(self, reply, address, params): self._call_validator('rcpt', reply, address, params) if reply.code == '250': self.envelope.recipients.append(address) def DATA(self, reply): self._call_validator('data', reply) def HAVE_DATA(self, reply, data, err): if isinstance(err, MessageTooBig): reply.code = '552' reply.message = '5.3.4 Message exceeded size limit' return elif err: raise err self._call_validator('have_data', reply, data) if reply.code != '250': return if self._ptr_lookup is not None: self.reverse_address = self._ptr_lookup.finish() self.envelope.client['ip'] = self.address[0] self.envelope.client['host'] = self.reverse_address self.envelope.client['name'] = self.ehlo_as self.envelope.client['protocol'] = self.protocol self.envelope.client['auth'] = self.auth self.envelope.parse(data) results = self.handoff(self.envelope) if isinstance(results[0][1], QueueError): default_reply = Reply('451', '4.3.0 Error queuing message') queue_reply = getattr(results[0][1], 'reply', default_reply) reply.copy(queue_reply) elif isinstance(results[0][1], RelayError): relay_reply = results[0][1].reply reply.copy(relay_reply) else: reply.message = '2.6.0 Message accepted for delivery' self._call_validator('queued', reply, results) self.envelope = None
def BANNER_(self, reply): self._ptr_lookup = PtrLookup(self.address[0]) self._ptr_lookup.start() self._call_validator('banner', reply, self.address)
class SmtpSession(object): def __init__(self, address, validator_class, handoff): self.extended_smtp = False self.security = None self.address = address self.reverse_address = None self.handoff = handoff self.validators = validator_class(self) if validator_class else None self.envelope = None self.ehlo_as = None self.auth = None def _call_validator(self, command, *args): method = "handle_" + command if hasattr(self.validators, method): getattr(self.validators, method)(*args) @property def protocol(self): proto = "SMTP" if self.extended_smtp: proto = "ESMTP" if self.security == "TLS": proto += "S" if self.auth: proto += "A" return proto def BANNER_(self, reply): self._ptr_lookup = PtrLookup(self.address[0]) self._ptr_lookup.start() self._call_validator("banner", reply, self.address) def EHLO(self, reply, ehlo_as): self._call_validator("ehlo", reply, ehlo_as) self.extended_smtp = True if reply.code == "250": self.ehlo_as = ehlo_as self.envelope = None def HELO(self, reply, helo_as): self._call_validator("helo", reply, helo_as) if reply.code == "250": self.ehlo_as = helo_as self.envelope = None def TLSHANDSHAKE(self): self._call_validator("tls") self.security = "TLS" def AUTH(self, reply, creds): self._call_validator("auth", reply, creds) if reply.code == "235": self.auth = creds.authcid def RSET(self, reply): self.envelope = None def MAIL(self, reply, address, params): self._call_validator("mail", reply, address, params) if reply.code == "250": self.envelope = Envelope(sender=address) def RCPT(self, reply, address, params): self._call_validator("rcpt", reply, address, params) if reply.code == "250": self.envelope.recipients.append(address) def DATA(self, reply): self._call_validator("data", reply) def HAVE_DATA(self, reply, data, err): if isinstance(err, MessageTooBig): reply.code = "552" reply.message = "5.3.4 Message exceeded size limit" return elif err: raise err self._call_validator("have_data", reply, data) if reply.code != "250": return self.envelope.client["ip"] = self.address[0] self.envelope.client["host"] = self.reverse_address self.envelope.client["name"] = self.ehlo_as self.envelope.client["protocol"] = self.protocol self.envelope.client["auth"] = self.auth self.envelope.parse(data) results = self.handoff(self.envelope) if isinstance(results[0][1], QueueError): reply.code = "550" reply.message = "5.6.0 Error queuing message" elif isinstance(results[0][1], RelayError): relay_reply = results[0][1].reply reply.copy(relay_reply) else: reply.message = "2.6.0 Message accepted for delivery" self.envelope = None
class SmtpSession(object): def __init__(self, address, validator_class, handoff): self.extended_smtp = False self.security = None self.address = address self.reverse_address = None self.handoff = handoff self.validators = validator_class(self) if validator_class else None self.envelope = None self.ehlo_as = None self.auth = None def _call_validator(self, command, *args): method = 'handle_'+command if hasattr(self.validators, method): getattr(self.validators, method)(*args) @property def protocol(self): proto = 'SMTP' if self.extended_smtp: proto = 'ESMTP' if self.security == 'TLS': proto += 'S' if self.auth: proto += 'A' return proto def BANNER_(self, reply): self._ptr_lookup = PtrLookup(self.address[0]) self._ptr_lookup.start() self._call_validator('banner', reply, self.address) def EHLO(self, reply, ehlo_as): self._call_validator('ehlo', reply, ehlo_as) self.extended_smtp = True if reply.code == '250': self.ehlo_as = ehlo_as self.envelope = None def HELO(self, reply, helo_as): self._call_validator('helo', reply, helo_as) if reply.code == '250': self.ehlo_as = helo_as self.envelope = None def TLSHANDSHAKE(self): self._call_validator('tls') self.security = 'TLS' def AUTH(self, reply, creds): self._call_validator('auth', reply, creds) if reply.code == '235': self.auth = creds.authcid def RSET(self, reply): self.envelope = None def MAIL(self, reply, address, params): self._call_validator('mail', reply, address, params) if reply.code == '250': self.envelope = Envelope(sender=address) def RCPT(self, reply, address, params): self._call_validator('rcpt', reply, address, params) if reply.code == '250': self.envelope.recipients.append(address) def DATA(self, reply): self._call_validator('data', reply) def HAVE_DATA(self, reply, data, err): if isinstance(err, MessageTooBig): reply.code = '552' reply.message = '5.3.4 Message exceeded size limit' return elif err: raise err self._call_validator('have_data', reply, data) if reply.code != '250': return self.envelope.client['ip'] = self.address[0] self.envelope.client['host'] = self.reverse_address self.envelope.client['name'] = self.ehlo_as self.envelope.client['protocol'] = self.protocol self.envelope.client['auth'] = self.auth self.envelope.parse(data) results = self.handoff(self.envelope) if isinstance(results[0][1], QueueError): default_reply = Reply('451', '4.3.0 Error queuing message') queue_reply = getattr(results[0][1], 'reply', default_reply) reply.copy(queue_reply) elif isinstance(results[0][1], RelayError): relay_reply = results[0][1].reply reply.copy(relay_reply) else: reply.message = '2.6.0 Message accepted for delivery' self._call_validator('queued', reply, results) self.envelope = None
def test_run_bad_ip(self): self.mox.ReplayAll() ptr = PtrLookup('abcd') self.assertIsInstance(ptr, gevent.Greenlet) self.assertIsNone(ptr._run())