From 25f87607aab0de024be90d6e6d0e96c19e827f49 Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Sat, 21 Jan 2012 00:44:03 -0800 Subject: [PATCH] Add support for X-GOOGLE-TOKEN. This is mainly just useful for authenticating without using TLS. If an access token is not provided, an attempt will be made to retrieve one from Google. --- .../thirdparty/suelta/mechanisms/__init__.py | 1 + .../suelta/mechanisms/google_token.py | 78 +++++++++++++++++++ .../thirdparty/suelta/mechanisms/plain.py | 2 +- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 sleekxmpp/thirdparty/suelta/mechanisms/google_token.py diff --git a/sleekxmpp/thirdparty/suelta/mechanisms/__init__.py b/sleekxmpp/thirdparty/suelta/mechanisms/__init__.py index e3facde..2044ff8 100644 --- a/sleekxmpp/thirdparty/suelta/mechanisms/__init__.py +++ b/sleekxmpp/thirdparty/suelta/mechanisms/__init__.py @@ -5,3 +5,4 @@ from sleekxmpp.thirdparty.suelta.mechanisms.digest_md5 import DIGEST_MD5 from sleekxmpp.thirdparty.suelta.mechanisms.scram_hmac import SCRAM_HMAC from sleekxmpp.thirdparty.suelta.mechanisms.messenger_oauth2 import X_MESSENGER_OAUTH2 from sleekxmpp.thirdparty.suelta.mechanisms.facebook_platform import X_FACEBOOK_PLATFORM +from sleekxmpp.thirdparty.suelta.mechanisms.google_token import X_GOOGLE_TOKEN diff --git a/sleekxmpp/thirdparty/suelta/mechanisms/google_token.py b/sleekxmpp/thirdparty/suelta/mechanisms/google_token.py new file mode 100644 index 0000000..75c55f1 --- /dev/null +++ b/sleekxmpp/thirdparty/suelta/mechanisms/google_token.py @@ -0,0 +1,78 @@ +import sys +import logging +try: + from httplib import HTTPSConnection + from urllib import urlencode +except ImportError: + from urllib.parse import urlencode + from http.client import HTTPSConnection + +from sleekxmpp.thirdparty.suelta.util import bytes +from sleekxmpp.thirdparty.suelta.sasl import Mechanism, register_mechanism +from sleekxmpp.thirdparty.suelta.exceptions import SASLError, SASLCancelled + + +log = logging.getLogger(__name__) + + +class X_GOOGLE_TOKEN(Mechanism): + + def __init__(self, sasl, name): + super(X_GOOGLE_TOKEN, self).__init__(sasl, name) + self.check_values(['email', 'password', 'access_token']) + + def process(self, challenge=None): + if not self.values.get('access_token', False): + log.debug("SASL: Requesting auth token from Google") + try: + conn = HTTPSConnection('www.google.com') + except: + raise SASLError(self.sasl, 'Could not connect to Google') + params = urlencode({ + 'accountType': 'GOOGLE', + 'service': 'mail', + 'Email': self.values['email'], + 'Passwd': self.values['password'] + }) + headers = { + 'Content-Type': 'application/x-www-form-urlencoded' + } + try: + conn.request('POST', '/accounts/ClientLogin', params, headers) + resp = conn.getresponse().read() + data = {} + for line in resp.split(): + k, v = line.split(b'=') + data[k] = v + except Exception as e: + raise e + #raise SASLError(self.sasl, 'Could not retrieve login data') + + if b'SID' not in data: + raise SASLError(self.sasl, 'Required data not found') + + params = urlencode({ + 'SID': data[b'SID'], + 'LSID': data[b'LSID'], + 'service': 'mail' + }) + try: + conn.request('POST', '/accounts/IssueAuthToken', params, headers) + resp = conn.getresponse() + data = resp.read().split() + except: + raise SASLError(self.sasl, 'Could not retrieve auth data') + if not data: + raise SASLError(self.sasl, 'Could not retrieve token') + + self.values['access_token'] = data[0] + + email = bytes(self.values['email']) + token = bytes(self.values['access_token']) + return b'\x00' + email + b'\x00' + token + + def okay(self): + return True + + +register_mechanism('X-GOOGLE-TOKEN', 3, X_GOOGLE_TOKEN, use_hashes=False) diff --git a/sleekxmpp/thirdparty/suelta/mechanisms/plain.py b/sleekxmpp/thirdparty/suelta/mechanisms/plain.py index ab17095..accae54 100644 --- a/sleekxmpp/thirdparty/suelta/mechanisms/plain.py +++ b/sleekxmpp/thirdparty/suelta/mechanisms/plain.py @@ -58,4 +58,4 @@ class PLAIN(Mechanism): return True -register_mechanism('PLAIN', 1, PLAIN, use_hashes=False) +register_mechanism('PLAIN', 5, PLAIN, use_hashes=False)