changeset 9f4a4fe90ae6 in /home/hg/repos/python-nbxmpp
details:http://hg.gajim.org/python-nbxmpp?cmd=changeset;node=9f4a4fe90ae6 description: fix encoding issues (base64, HMAC, ...)
diffstat:
nbxmpp/auth_nb.py | 44 ++++++++++++++++++++++++++------------------ nbxmpp/dispatcher_nb.py | 24 ++++++++++++++---------- nbxmpp/proxy_connectors.py | 6 ++++-- nbxmpp/simplexml.py | 2 +- nbxmpp/tls_nb.py | 6 ++++-- 5 files changed, 49 insertions(+), 33 deletions(-)
diffs (242 lines):
diff -r 220e1936c4d2 -r 9f4a4fe90ae6 nbxmpp/auth_nb.py --- a/nbxmpp/auth_nb.py Wed Jan 02 14:15:21 2013 +0100 +++ b/nbxmpp/auth_nb.py Wed Jan 02 15:36:55 2013 +0100 @@ -219,8 +219,8 @@ if "EXTERNAL" in self.mecs: self.mecs.remove('EXTERNAL') sasl_data = '%s@%s' % (self.username, self._owner.Server) - sasl_data = sasl_data.encode('utf-8').encode('base64').replace( - '\n', '') + sasl_data = base64.b64encode(sasl_data.encode('utf-8')).decode( + 'utf-8').replace('\n', '') node = Node('auth', attrs={'xmlns': NS_SASL, 'mechanism': 'EXTERNAL'}, payload=[sasl_data]) self.mechanism = 'EXTERNAL' @@ -285,10 +285,15 @@ return
def scram_base64(s): - return ''.join(s.encode('base64').split('\n')) + try: + s = s.encode('utf-8') + except: + pass + return ''.join(base64.b64encode(s).decode('utf-8').\ + split('\n'))
incoming_data = challenge.getData() - data=base64.decodestring(incoming_data) + data=base64.b64decode(incoming_data.encode('utf-8')).decode('utf-8') ### Handle Auth result def on_auth_fail(reason): log.info('Failed SASL authentification: %s' % reason) @@ -361,11 +366,11 @@ hashfn = hashlib.sha1
def HMAC(k, s): - return hmac.HMAC(key=k, msg=s, digestmod=hashfn).digest() + return hmac.new(key=k, msg=s, digestmod=hashfn).digest()
def XOR(x, y): - r = (chr(ord(px) ^ ord(py)) for px, py in zip(x, y)) - return ''.join(r) + r = [px ^ py for px, py in zip(x, y)] + return bytes(r)
def Hi(s, salt, iters): ii = 1 @@ -373,7 +378,7 @@ s = s.encode('utf-8') except: pass - ui_1 = HMAC(s, salt + '\0\0\0\01') + ui_1 = HMAC(s, (salt + '\0\0\0\01').encode('utf-8')) ui = ui_1 for i in range(iters - 1): ii += 1 @@ -393,16 +398,18 @@ r = 'c=' + scram_base64(self.scram_gs2) r += ',r=' + data['r'] self.scram_soup += r - salt = data['s'].decode('base64') + self.scram_soup = self.scram_soup.encode('utf-8') + salt = base64.b64decode(data['s'].encode('utf-8')).decode( + 'utf-8') iter = int(data['i']) SaltedPassword = Hi(self.password, salt, iter) # TODO: Could cache this, along with salt+iter. - ClientKey = HMAC(SaltedPassword, 'Client Key') + ClientKey = HMAC(SaltedPassword, b'Client Key') StoredKey = scram_H(ClientKey) ClientSignature = HMAC(StoredKey, self.scram_soup) ClientProof = XOR(ClientKey, ClientSignature) r += ',p=' + scram_base64(ClientProof) - ServerKey = HMAC(SaltedPassword, 'Server Key') + ServerKey = HMAC(SaltedPassword, b'Server Key') self.scram_ServerSignature = HMAC(ServerKey, self.scram_soup) sasl_data = scram_base64(r) node = Node('response', attrs={'xmlns': NS_SASL}, @@ -412,7 +419,8 @@
if self.scram_step == 1: data = scram_parse(data) - if data['v'].decode('base64') != self.scram_ServerSignature: + if base64.b64decode(data['v'].encode('utf-8')).decode('utf-8') \ + != self.scram_ServerSignature: # TODO: Not clear what to do here - need to abort. raise Exception node = Node('response', attrs={'xmlns': NS_SASL}); @@ -468,8 +476,8 @@ itertools.repeat(random.randint, 7)) self.scram_soup = 'n=' + self.username + ',r=' + nonce self.scram_gs2 = 'n,,' # No CB yet. - sasl_data = (self.scram_gs2 + self.scram_soup).encode('base64').\ - replace('\n', '') + sasl_data = base64.b64encode((self.scram_gs2 + self.scram_soup).\ + encode('utf-8')).decode('utf-8').replace('\n', '') node = Node('auth', attrs={'xmlns': NS_SASL, 'mechanism': self.mechanism}, payload=[sasl_data]) elif self.mechanism == 'DIGEST-MD5': @@ -493,14 +501,14 @@ sasl_data += "%s=%s," % (key, self.resp[key]) else: sasl_data += '%s="%s",' % (key, self.resp[key]) - sasl_data = sasl_data[:-1].encode('utf-8').encode('base64').replace( - '\r', '').replace('\n', '') + sasl_data = base64.b64encode(sasl_data[:-1].encode('utf-8')).\ + decode('utf-8').replace('\r', '').replace('\n', '') node = Node('response', attrs={'xmlns': NS_SASL}, payload=[sasl_data]) elif self.mechanism == 'PLAIN': sasl_data = '\x00%s\x00%s' % (self.username, self.password) - sasl_data = sasl_data.encode('utf-8').encode('base64').replace( - '\n', '') + sasl_data = base64.b64encode(sasl_data.encode('utf-8')).decode( + 'utf-8').replace('\n', '') node = Node('auth', attrs={'xmlns': NS_SASL, 'mechanism': 'PLAIN'}, payload=[sasl_data]) elif self.mechanism == 'X-MESSENGER-OAUTH2': diff -r 220e1936c4d2 -r 9f4a4fe90ae6 nbxmpp/dispatcher_nb.py --- a/nbxmpp/dispatcher_nb.py Wed Jan 02 14:15:21 2013 +0100 +++ b/nbxmpp/dispatcher_nb.py Wed Jan 02 15:36:55 2013 +0100 @@ -98,21 +98,21 @@
# \ufddo -> \ufdef range c = '\ufdd0' - r = c.encode('utf8') + r = c while (c < '\ufdef'): c = chr(ord(c) + 1) - r += '|' + c.encode('utf8') + r += '|' + c
# \ufffe-\uffff, \u1fffe-\u1ffff, ..., \u10fffe-\u10ffff c = '\ufffe' - r += '|' + c.encode('utf8') - r += '|' + chr(ord(c) + 1).encode('utf8') + r += '|' + c + r += '|' + chr(ord(c) + 1) while (c < '\U0010fffe'): c = chr(ord(c) + 0x10000) - r += '|' + c.encode('utf8') - r += '|' + chr(ord(c) + 1).encode('utf8') + r += '|' + c + r += '|' + chr(ord(c) + 1)
- self.invalid_chars_re = re.compile(r) + self.invalid_chars_re = re.compile(r.encode('utf-8'))
def getAnID(self): global outgoingID @@ -222,7 +222,9 @@ handler(self) if len(self._pendingExceptions) > 0: _pendingException = self._pendingExceptions.pop() - raise _pendingException + e = _pendingException[0](_pendingException[1]) + e.__traceback__ = _pendingException[2] + raise e try: self.Stream.Parse(data) # end stream:stream tag received @@ -239,7 +241,9 @@ return 0 if len(self._pendingExceptions) > 0: _pendingException = self._pendingExceptions.pop() - raise _pendingException + e = _pendingException[0](_pendingException[1]) + e.__traceback__ = _pendingException[2] + raise e if len(data) == 0: return '0' return len(data) @@ -507,7 +511,7 @@ # we have released dispatcher, so self._owner has no methods if not res: return - for (_id, _iq) in self._expected.items(): + for (_id, _iq) in list(self._expected.items()): if _iq is None: # If the expected Stanza would have arrived, ProcessNonBlocking # would have placed the reply stanza in there diff -r 220e1936c4d2 -r 9f4a4fe90ae6 nbxmpp/proxy_connectors.py --- a/nbxmpp/proxy_connectors.py Wed Jan 02 14:15:21 2013 +0100 +++ b/nbxmpp/proxy_connectors.py Wed Jan 02 15:36:55 2013 +0100 @@ -22,7 +22,8 @@ Authentication to NTLM (Microsoft implementation) proxies can be next. """
-import struct, socket, base64 +import struct, socket +from base64 import b64encode import logging log = logging.getLogger('nbxmpp.proxy_connectors')
@@ -91,7 +92,8 @@ 'User-Agent: Gajim'] if self.proxy_user and self.proxy_pass: credentials = '%s:%s' % (self.proxy_user, self.proxy_pass) - credentials = base64.encodestring(credentials).strip() + credentials = b64encode(credentials.encode('utf-8')).decode( + 'utf-8').strip() connector.append('Proxy-Authorization: Basic '+credentials) connector.append('\r\n') self.onreceive(self._on_headers_sent) diff -r 220e1936c4d2 -r 9f4a4fe90ae6 nbxmpp/simplexml.py --- a/nbxmpp/simplexml.py Wed Jan 02 14:15:21 2013 +0100 +++ b/nbxmpp/simplexml.py Wed Jan 02 15:36:55 2013 +0100 @@ -163,7 +163,7 @@ for a in self.kids: if not fancy and (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt]) elif (len(self.data)-1)>=cnt: s=s+XMLescape(self.data[cnt].strip()) - if isinstance(a, str) or isinstance(a, str): + if isinstance(a, str): s = s + a.__str__() else: s = s + a.__str__(fancy and fancy+1) diff -r 220e1936c4d2 -r 9f4a4fe90ae6 nbxmpp/tls_nb.py --- a/nbxmpp/tls_nb.py Wed Jan 02 14:15:21 2013 +0100 +++ b/nbxmpp/tls_nb.py Wed Jan 02 15:36:55 2013 +0100 @@ -345,6 +345,7 @@ '%s' % cert_path) begin = -1 i += 1 + f.close()
def _startSSL_pyOpenSSL(self): log.debug("_startSSL_pyOpenSSL called") @@ -449,11 +450,12 @@ def _ssl_verify_callback(self, sslconn, cert, errnum, depth, ok): # Exceptions can't propagate up through this callback, so print them here. try: - self._owner.ssl_fingerprint_sha1.append(cert.digest('sha1')) + self._owner.ssl_fingerprint_sha1.append(cert.digest('sha1').decode( + 'utf-8')) self._owner.ssl_certificate.append(cert) self._owner.ssl_errnum.append(errnum) self._owner.ssl_cert_pem.append(OpenSSL.crypto.dump_certificate( - OpenSSL.crypto.FILETYPE_PEM, cert)) + OpenSSL.crypto.FILETYPE_PEM, cert).decode('utf-8')) return True except: log.error("Exception caught in _ssl_info_callback:", exc_info=True)