Compare commits

...

11 Commits

Author SHA1 Message Date
Lance Stout
753cb3580e Bump to 1.3.0 2014-06-08 20:01:07 -07:00
Lance Stout
60b050b82a Make ssl args work in Python <=2.6.4 2014-06-08 19:59:40 -07:00
Lance Stout
ad91a8cd5e Bring back use of dnspython for A/AAAA resolution.
This is behind a use_dnspython flag, however, so it can be disabled as
desired.
2014-06-08 19:51:57 -07:00
Lance Stout
02f79fc94b Only request auto-receipts for messages with bodies 2014-06-07 20:20:42 -07:00
Lance Stout
230a73fad2 Fix own_host in ping plugin 2014-06-07 20:06:17 -07:00
Lance Stout
d94dd486fe Merge pull request #294 from mofrank/develop
Fixes log.debug message in _connect_proxy
2014-05-16 08:43:39 -07:00
Lance Stout
6ecc39b816 Merge pull request #292 from 4gra/develop
Fix support for jabberd2 with GSSAPI
2014-05-16 08:43:26 -07:00
mofrank
9c240df9db Fixes log.debug message in _connect_proxy 2014-05-16 08:49:01 -05:00
Graham
a918bf3a95 Support jabberd2 SASL with really empty response
Despite http://xmpp.org/rfcs/rfc3920.html#rfc.section.6.2, jabberd version 2.2.14 cannot accept the typical "<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">=</response>".  Instead it must be truly empty, so we force an empty response for this stanza only.
2014-05-14 22:32:51 +01:00
Graham
9434ae267f support 'success' phase correctly
When the GSSAPI mechanism's process() function is invoked for the third time (on success) it must not attempt further processing.  Instead it should clean the context and return an empty response.
2014-05-14 22:25:09 +01:00
Graham
94187d215a don't use the kerberos.GSSError.message attribute
Replaced the reference to kerberos.GSSError.message in any raised exception, because:

 DeprecationWarning: BaseException.message has been deprecated as of Python 2.6

and its natural repr is probably the most desirable output.
2014-05-14 17:47:34 +01:00
8 changed files with 114 additions and 42 deletions

View File

@@ -45,7 +45,7 @@ The latest source code for SleekXMPP may be found on `Github
``develop`` branch.
**Latest Release**
- `1.2.5 <http://github.com/fritzy/SleekXMPP/zipball/1.2.5>`_
- `1.3.0 <http://github.com/fritzy/SleekXMPP/zipball/1.3.0>`_
**Develop Releases**
- `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_

View File

@@ -215,6 +215,8 @@ class FeatureMechanisms(BasePlugin):
self.attempted_mechs.add(self.mech.name)
self.xmpp.disconnect()
else:
if resp.get_value() == '':
resp.del_value()
resp.send(now=True)
def _handle_success(self, stanza):

View File

@@ -118,6 +118,9 @@ class XEP_0184(BasePlugin):
if stanza['receipt']:
return stanza
if not stanza['body']:
return stanza
if stanza['to'].resource:
if not self.xmpp['xep_0030'].supports(stanza['to'],
feature='urn:xmpp:receipts',

View File

@@ -154,6 +154,7 @@ class XEP_0199(BasePlugin):
timeout -- Time in seconds to wait for a response.
Defaults to self.timeout.
"""
own_host = False
if not jid:
if self.xmpp.is_component:
jid = self.xmpp.server

View File

@@ -532,6 +532,9 @@ else:
result = kerberos.authGSSClientStep(self.gss, b64_challenge)
if result != kerberos.AUTH_GSS_CONTINUE:
self.step = 1
elif not challenge:
kerberos.authGSSClientClean(self.gss)
return b''
elif self.step == 1:
username = self.credentials['username']
@@ -541,7 +544,7 @@ else:
resp = kerberos.authGSSClientResponse(self.gss)
except kerberos.GSSError as e:
raise SASLCancelled('Kerberos error: %s' % e.message)
raise SASLCancelled('Kerberos error: %s' % e)
if not resp:
return b''
else:

View File

@@ -9,5 +9,5 @@
# We don't want to have to import the entire library
# just to get the version info for setup.py
__version__ = '1.2.5'
__version_info__ = (1, 2, 5, '', 0)
__version__ = '1.3.0'
__version_info__ = (1, 3, 0, '', 0)

View File

@@ -32,10 +32,10 @@ log = logging.getLogger(__name__)
#: cd dnspython
#: git checkout python3
#: python3 setup.py install
USE_DNSPYTHON = False
DNSPYTHON_AVAILABLE = False
try:
import dns.resolver
USE_DNSPYTHON = True
DNSPYTHON_AVAILABLE = True
except ImportError as e:
log.debug("Could not find dnspython package. " + \
"Not all features will be available")
@@ -47,13 +47,13 @@ def default_resolver():
:returns: A :class:`dns.resolver.Resolver` object if dnspython
is available. Otherwise, ``None``.
"""
if USE_DNSPYTHON:
if DNSPYTHON_AVAILABLE:
return dns.resolver.get_default_resolver()
return None
def resolve(host, port=None, service=None, proto='tcp',
resolver=None, use_ipv6=True):
resolver=None, use_ipv6=True, use_dnspython=True):
"""Peform DNS resolution for a given hostname.
Resolution may perform SRV record lookups if a service and protocol
@@ -77,6 +77,9 @@ def resolve(host, port=None, service=None, proto='tcp',
:param use_ipv6: Optionally control the use of IPv6 in situations
where it is either not available, or performance
is degraded. Defaults to ``True``.
:param use_dnspython: Optionally control if dnspython is used to make
the DNS queries instead of the built-in DNS
library.
:type host: string
:type port: int
@@ -84,14 +87,22 @@ def resolve(host, port=None, service=None, proto='tcp',
:type proto: string
:type resolver: :class:`dns.resolver.Resolver`
:type use_ipv6: bool
:type use_dnspython: bool
:return: An iterable of IP address, port pairs in the order
dictated by SRV priorities and weights, if applicable.
"""
if not use_dnspython:
if DNSPYTHON_AVAILABLE:
log.debug("DNS: Not using dnspython, but dnspython is installed.")
else:
log.debug("DNS: Not using dnspython.")
if not use_ipv6:
log.debug("DNS: Use of IPv6 has been disabled.")
if resolver is None and USE_DNSPYTHON:
if resolver is None and DNSPYTHON_AVAILABLE and use_dnspython:
resolver = dns.resolver.get_default_resolver()
# An IPv6 literal is allowed to be enclosed in square brackets, but
@@ -122,7 +133,9 @@ def resolve(host, port=None, service=None, proto='tcp',
if not service:
hosts = [(host, port)]
else:
hosts = get_SRV(host, port, service, proto, resolver=resolver)
hosts = get_SRV(host, port, service, proto,
resolver=resolver,
use_dnspython=use_dnspython)
for host, port in hosts:
results = []
@@ -131,16 +144,18 @@ def resolve(host, port=None, service=None, proto='tcp',
results.append((host, '::1', port))
results.append((host, '127.0.0.1', port))
if use_ipv6:
for address in get_AAAA(host):
for address in get_AAAA(host, resolver=resolver,
use_dnspython=use_dnspython):
results.append((host, address, port))
for address in get_A(host):
for address in get_A(host, resolver=resolver,
use_dnspython=use_dnspython):
results.append((host, address, port))
for host, address, port in results:
yield host, address, port
def get_A(host):
def get_A(host, resolver=None, use_dnspython=True):
"""Lookup DNS A records for a given host.
If ``resolver`` is not provided, or is ``None``, then resolution will
@@ -148,9 +163,13 @@ def get_A(host):
:param host: The hostname to resolve for A record IPv4 addresses.
:param resolver: Optional DNS resolver object to use for the query.
:param use_dnspython: Optionally control if dnspython is used to make
the DNS queries instead of the built-in DNS
library.
:type host: string
:type resolver: :class:`dns.resolver.Resolver` or ``None``
:type use_dnspython: bool
:return: A list of IPv4 literals.
"""
@@ -158,15 +177,32 @@ def get_A(host):
# If not using dnspython, attempt lookup using the OS level
# getaddrinfo() method.
if resolver is None or not use_dnspython:
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET,
socket.SOCK_STREAM)
return [rec[4][0] for rec in recs]
except socket.gaierror:
log.debug("DNS: Error retreiving A address info for %s." % host)
return []
# Using dnspython:
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET,
socket.SOCK_STREAM)
return [rec[4][0] for rec in recs]
except socket.gaierror:
log.debug("DNS: Error retreiving A address info for %s." % host)
recs = resolver.query(host, dns.rdatatype.A)
return [rec.to_text() for rec in recs]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
log.debug("DNS: No A records for %s" % host)
return []
except dns.exception.Timeout:
log.debug("DNS: A record resolution timed out for %s" % host)
return []
except dns.exception.DNSException as e:
log.debug("DNS: Error querying A records for %s" % host)
log.exception(e)
return []
def get_AAAA(host):
def get_AAAA(host, resolver=None, use_dnspython=True):
"""Lookup DNS AAAA records for a given host.
If ``resolver`` is not provided, or is ``None``, then resolution will
@@ -174,9 +210,13 @@ def get_AAAA(host):
:param host: The hostname to resolve for AAAA record IPv6 addresses.
:param resolver: Optional DNS resolver object to use for the query.
:param use_dnspython: Optionally control if dnspython is used to make
the DNS queries instead of the built-in DNS
library.
:type host: string
:type resolver: :class:`dns.resolver.Resolver` or ``None``
:type use_dnspython: bool
:return: A list of IPv6 literals.
"""
@@ -184,19 +224,36 @@ def get_AAAA(host):
# If not using dnspython, attempt lookup using the OS level
# getaddrinfo() method.
if not socket.has_ipv6:
log.debug("Unable to query %s for AAAA records: IPv6 is not supported", host)
return []
if resolver is None or not use_dnspython:
if not socket.has_ipv6:
log.debug("Unable to query %s for AAAA records: IPv6 is not supported", host)
return []
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET6,
socket.SOCK_STREAM)
return [rec[4][0] for rec in recs]
except (OSError, socket.gaierror):
log.debug("DNS: Error retreiving AAAA address " + \
"info for %s." % host)
return []
# Using dnspython:
try:
recs = socket.getaddrinfo(host, None, socket.AF_INET6,
socket.SOCK_STREAM)
return [rec[4][0] for rec in recs]
except (OSError, socket.gaierror):
log.debug("DNS: Error retreiving AAAA address " + \
"info for %s." % host)
recs = resolver.query(host, dns.rdatatype.AAAA)
return [rec.to_text() for rec in recs]
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
log.debug("DNS: No AAAA records for %s" % host)
return []
except dns.exception.Timeout:
log.debug("DNS: AAAA record resolution timed out for %s" % host)
return []
except dns.exception.DNSException as e:
log.debug("DNS: Error querying AAAA records for %s" % host)
log.exception(e)
return []
def get_SRV(host, port, service, proto='tcp', resolver=None):
def get_SRV(host, port, service, proto='tcp', resolver=None, use_dnspython=True):
"""Perform SRV record resolution for a given host.
.. note::
@@ -222,7 +279,7 @@ def get_SRV(host, port, service, proto='tcp', resolver=None):
:return: A list of hostname, port pairs in the order dictacted
by SRV priorities and weights.
"""
if resolver is None:
if resolver is None or not use_dnspython:
log.warning("DNS: dnspython not found. Can not use SRV lookup.")
return [(host, port)]

View File

@@ -224,6 +224,11 @@ class XMLStream(object):
#: If set to ``True``, attempt to use IPv6.
self.use_ipv6 = True
#: If set to ``True``, allow using the ``dnspython`` DNS library
#: if available. If set to ``False``, the builtin DNS resolver
#: will be used, even if ``dnspython`` is installed.
self.use_dnspython = True
#: Use CDATA for escaping instead of XML entities. Defaults
#: to ``False``.
self.use_cdata = False
@@ -514,11 +519,11 @@ class XMLStream(object):
cert_policy = ssl.CERT_REQUIRED
ssl_args = {
'certfile': self.certfile,
'keyfile': self.keyfile,
'ca_certs': self.ca_certs,
'cert_reqs': cert_policy,
'do_handshake_on_connect': False,
b'certfile': self.certfile,
b'keyfile': self.keyfile,
b'ca_certs': self.ca_certs,
b'cert_reqs': cert_policy,
b'do_handshake_on_connect': False,
}
if sys.version_info >= (2, 7):
@@ -611,7 +616,7 @@ class XMLStream(object):
headers = '\r\n'.join(headers) + '\r\n\r\n'
try:
log.debug("Connecting to proxy: %s:%s", address)
log.debug("Connecting to proxy: %s:%s", *address)
self.socket.connect(address)
self.send_raw(headers, now=True)
resp = ''
@@ -838,11 +843,11 @@ class XMLStream(object):
cert_policy = ssl.CERT_REQUIRED
ssl_args = {
'certfile': self.certfile,
'keyfile': self.keyfile,
'ca_certs': self.ca_certs,
'cert_reqs': cert_policy,
'do_handshake_on_connect': False,
b'certfile': self.certfile,
b'keyfile': self.keyfile,
b'ca_certs': self.ca_certs,
b'cert_reqs': cert_policy,
b'do_handshake_on_connect': False,
}
if sys.version_info >= (2, 7):
@@ -1081,7 +1086,8 @@ class XMLStream(object):
return resolve(domain, port, service=self.dns_service,
resolver=resolver,
use_ipv6=self.use_ipv6)
use_ipv6=self.use_ipv6,
use_dnspython=self.use_dnspython)
def pick_dns_answer(self, domain, port=None):
"""Pick a server and port from DNS answers.