Hello community, here is the log from the commit of package python-pure-sasl for openSUSE:Factory checked in at 2018-05-29 10:32:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pure-sasl (Old) and /work/SRC/openSUSE:Factory/.python-pure-sasl.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pure-sasl" Tue May 29 10:32:41 2018 rev:3 rq:610618 version:0.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pure-sasl/python-pure-sasl.changes 2018-03-09 10:47:33.880584611 +0100 +++ /work/SRC/openSUSE:Factory/.python-pure-sasl.new/python-pure-sasl.changes 2018-05-29 10:32:43.603501429 +0200 @@ -1,0 +2,8 @@ +Sat May 19 11:34:20 UTC 2018 - [email protected] + +- Update to 0.5.1 + * Fixes for DIGEST-MD5, server auth has been completed and is now + tested + * Both DIGEST-MD5 and CRAM-MD5 properly set the complete flag now + +------------------------------------------------------------------- Old: ---- pure-sasl-0.5.0.tar.gz New: ---- pure-sasl-0.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pure-sasl.spec ++++++ --- /var/tmp/diff_new_pack.ZpCiHt/_old 2018-05-29 10:32:45.083446769 +0200 +++ /var/tmp/diff_new_pack.ZpCiHt/_new 2018-05-29 10:32:45.083446769 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without test Name: python-pure-sasl -Version: 0.5.0 +Version: 0.5.1 Release: 0 Summary: Pure Python client SASL implementation License: MIT ++++++ pure-sasl-0.5.0.tar.gz -> pure-sasl-0.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pure-sasl-0.5.0/CHANGES.rst new/pure-sasl-0.5.1/CHANGES.rst --- old/pure-sasl-0.5.0/CHANGES.rst 2018-03-09 06:04:26.000000000 +0100 +++ new/pure-sasl-0.5.1/CHANGES.rst 2018-05-19 01:09:41.000000000 +0200 @@ -1,3 +1,12 @@ +0.5.1 +===== +May 18th, 2018 + +* Fixes for DIGEST-MD5, server auth has been completed and is now tested +* Both DIGEST-MD5 and CRAM-MD5 properly set the complete flag now + +Thanks to @ceache and @bjmb for this release + 0.5.0 ===== March 8th, 2018 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pure-sasl-0.5.0/PKG-INFO new/pure-sasl-0.5.1/PKG-INFO --- old/pure-sasl-0.5.0/PKG-INFO 2018-03-09 06:09:02.000000000 +0100 +++ new/pure-sasl-0.5.1/PKG-INFO 2018-05-19 01:21:47.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pure-sasl -Version: 0.5.0 +Version: 0.5.1 Summary: Pure Python client SASL implementation Home-page: http://github.com/thobbs/pure-sasl Author: Alex Shafer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pure-sasl-0.5.0/pure_sasl.egg-info/PKG-INFO new/pure-sasl-0.5.1/pure_sasl.egg-info/PKG-INFO --- old/pure-sasl-0.5.0/pure_sasl.egg-info/PKG-INFO 2018-03-09 06:09:02.000000000 +0100 +++ new/pure-sasl-0.5.1/pure_sasl.egg-info/PKG-INFO 2018-05-19 01:21:46.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: pure-sasl -Version: 0.5.0 +Version: 0.5.1 Summary: Pure Python client SASL implementation Home-page: http://github.com/thobbs/pure-sasl Author: Alex Shafer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pure-sasl-0.5.0/puresasl/__init__.py new/pure-sasl-0.5.1/puresasl/__init__.py --- old/pure-sasl-0.5.0/puresasl/__init__.py 2018-03-09 06:04:26.000000000 +0100 +++ new/pure-sasl-0.5.1/puresasl/__init__.py 2018-05-19 01:09:41.000000000 +0200 @@ -1,5 +1,5 @@ -__version__ = '0.5.0' -__version_info__ = (0, 5, 0) +__version__ = '0.5.1' +__version_info__ = (0, 5, 1) class SASLError(Exception): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pure-sasl-0.5.0/puresasl/mechanisms.py new/pure-sasl-0.5.1/puresasl/mechanisms.py --- old/pure-sasl-0.5.0/puresasl/mechanisms.py 2018-03-09 06:03:17.000000000 +0100 +++ new/pure-sasl-0.5.1/puresasl/mechanisms.py 2018-05-19 00:38:40.000000000 +0200 @@ -210,13 +210,15 @@ self._fetch_properties('username', 'password') mac = hmac.HMAC(key=_b(self.password), digestmod=hashlib.md5) mac.update(challenge) + self.complete = True return b''.join((_b(self.username), b' ', _b(mac.hexdigest()))) def dispose(self): self.password = None -# functions used in DigestMD5 which were originally defined in the now-removed util module +# functions used in DigestMD5 which were originally defined in the now-removed +# util module def bytes(text): """ @@ -267,12 +269,10 @@ self.username = username self.password = password - self._rspauth_okay = False self._digest_uri = None self._a1 = None def dispose(self): - self._rspauth_okay = None self._digest_uri = None self._a1 = None @@ -318,29 +318,43 @@ a2 += b':00000000000000000000000000000000' resp['maxbuf'] = b'16777215' # 2**24-1 resp['response'] = self.gen_hash(a2) - return b','.join([bytes(k) + b'=' + bytes(v) for k, v in resp.items()]) + return b','.join( + [ + bytes(k) + b'=' + bytes(v) + for k, v in resp.items() + ] + ) @staticmethod def parse_challenge(challenge): + """Parse a digest challenge message. + + :param ``bytes`` challenge: + Challenge message from the server, in bytes. + :returns: + ``dict`` of ``str`` keyword to ``bytes`` values. + """ ret = {} - var = '' - val = '' + var = b'' + val = b'' in_var = True in_quotes = False new = False escaped = False for c in challenge: + if sys.version_info[0] == 3: + c = bytes([c]) if in_var: if c.isspace(): continue - if c == '=': + if c == b'=': in_var = False new = True else: var += c else: if new: - if c == '"': + if c == b'"': in_quotes = True else: val += c @@ -350,23 +364,23 @@ escaped = False val += c else: - if c == '\\': + if c == b'\\': escaped = True - elif c == '"': + elif c == b'"': in_quotes = False else: val += c else: - if c == ',': + if c == b',': if var: - ret[var] = bytes(val) - var = '' - val = '' + ret[var.decode('ascii')] = val + var = b'' + val = b'' in_var = True else: val += c if var: - ret[var] = val + ret[var.decode('ascii')] = val return ret def gen_hash(self, a2): @@ -393,13 +407,12 @@ response.update(rv) return bytes(response.hexdigest().lower()) - # untested def authenticate_server(self, cmp_hash): a2 = b':' + self._digest_uri if self.qop != QOP.AUTH: a2 += b':00000000000000000000000000000000' - if self.gen_hash(a2) == cmp_hash: - self._rspauth_okay = True + if self.gen_hash(a2) != cmp_hash: + raise SASLProtocolException('Invalid server auth response') def process(self, challenge=None): if challenge is None: @@ -411,28 +424,42 @@ return None challenge_dict = DigestMD5Mechanism.parse_challenge(challenge) - if self.sasl.mutual_auth and 'rspauth' in challenge_dict: + if 'rspauth' in challenge_dict: self.authenticate_server(challenge_dict['rspauth']) + self.complete = True + return None if 'realm' not in challenge_dict: self._fetch_properties('realm') challenge_dict['realm'] = self.realm for key in ('nonce', 'realm'): + # TODO: rfc2831#section-2.1.1 realm: "Multiple realm directives are + # allowed, in which case the user or client must choose one as the + # realm for which to supply to username and password" + # TODO: rfc2831#section-2.1.1 nonce: "This directive is required + # and MUST appear exactly once; if not present, or if multiple + # instances are present, the client should abort the authentication + # exchange" if key in challenge_dict: setattr(self, key, challenge_dict[key]) self.nc = 0 if 'qop' in challenge_dict: - server_offered_qops = [x.strip() for x in challenge_dict['qop'].split(b',')] + server_offered_qops = [ + x.strip() for x in challenge_dict['qop'].split(b',') + ] else: - server_offered_qops = ['auth'] + server_offered_qops = [QOP.AUTH] self._pick_qop(set(server_offered_qops)) if 'maxbuf' in challenge_dict: self.max_buffer = min( self.sasl.max_buffer, int(challenge_dict['maxbuf'])) + # TODO: rfc2831#section-2.1.1 algorithm: This directive is required and + # MUST appear exactly once; if not present, or if multiple instances + # are present, the client should abort the authentication exchange. return self.response()
