From a38fa1bbbeba22a1d60b2608d5eaf98a6b60a033 Mon Sep 17 00:00:00 2001 From: Marcus Huewe Date: Wed, 30 Mar 2011 01:40:43 +0200 Subject: [PATCH] - quick hack to support the OAuthHandler --- osc/OAuthHandler.py | 40 ++++++++++++++++++++++++++++++++++++++++ osc/conf.py | 23 +++++++++++++++++++---- 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 osc/OAuthHandler.py diff --git a/osc/OAuthHandler.py b/osc/OAuthHandler.py new file mode 100644 index 00000000..2748da6a --- /dev/null +++ b/osc/OAuthHandler.py @@ -0,0 +1,40 @@ +import oauth +import urlparse +import urllib2 +import sys + +class OAuthHandler(urllib2.BaseHandler): + def __init__(self, password_mgr = None): + if password_mgr is None: + password_mgr = urllib2.HTTPPasswordMgr() + self.passwd = password_mgr + self.add_password = self.passwd.add_password + + def http_error_401(self, req, fp, code, msg, headers): + # XXX: desktop clients etc. won't have a consumer token + secret => unknown + unknown will be used + auth_req = headers.get('www-authenticate', None) + scheme = None + if auth_req: + mo = urllib2.AbstractBasicAuthHandler.rx.search(auth_req) + if mo: + scheme = mo.groups()[0] + if not auth_req or scheme != 'oauth': + return None + # default consumer key + secret for desktop clients + consumer = oauth.OAuthConsumer('desktop', 'desktop') + atoken, secret = self.passwd.find_user_password(None, req.get_full_url()) + token = oauth.OAuthToken(atoken, secret) + query = dict(urlparse.parse_qsl(urlparse.urlsplit(req.get_full_url())[3])) + if query.has_key('oauth_token') or req.headers.get('Authorization', '').startswith('OAuth'): + return None + # XXX: pass the full url - it'll be converted by the oauth module + oauthreq = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, + http_method=req.get_method(), http_url=req.get_full_url(), parameters=query) + print consumer, token + oauthreq.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, token) + req.add_header(*oauthreq.to_header().items()[0]) + return self.parent.open(req) + + def get_handler(config, password_mgr = None): + return OAuthHandler(password_mgr) + get_handler = staticmethod(get_handler) diff --git a/osc/conf.py b/osc/conf.py index a7f31bd4..1da21d9a 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -425,11 +425,19 @@ def _build_opener(url): authhandler_class = OscHTTPBasicAuthHandler options = config['api_host_options'][apiurl] + accepted_auth_methods = ['basic;q=0.5'] # with None as first argument, it will always use this username/password # combination for urls for which arg2 (apisrv) is a super-url - authhandler = authhandler_class( \ - urllib2.HTTPPasswordMgrWithDefaultRealm()) - authhandler.add_password(None, apiurl, options['user'], options['pass']) + if options.has_key('auth_prot'): + # XXX: should the qvalue be configurable? + accepted_auth_methods.append('%s;q=0.8' % options['auth_prot'].lower()) + klass = getattr(__import__(options['auth_prot'] + 'Handler', globals()), options['auth_prot'] + 'Handler') + authhandler = klass.get_handler(config) + authhandler.add_password(None, apiurl, options['login'], options['pass']) + else: + authhandler = authhandler_class( \ + urllib2.HTTPPasswordMgrWithDefaultRealm()) + authhandler.add_password(None, apiurl, options['user'], options['pass']) if options['sslcertck']: try: @@ -457,6 +465,7 @@ def _build_opener(url): print >>sys.stderr, "WARNING: SSL certificate checks disabled. Connection is insecure!\n" opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar), authhandler) opener.addheaders = [('User-agent', 'osc/%s' % __version__)] + opener.addheaders.append(('Accept-Authentication', ','.join(set(accepted_auth_methods)))) _build_opener.last_opener = (apiurl, opener) return opener @@ -829,6 +838,9 @@ def get_config(override_conffile = None, http_headers = http_header_regexp.findall(http_headers) else: http_headers = [] + auth_prot = None + if cp.has_option(url, 'auth_prot'): + auth_prot = cp.get(url, 'auth_prot') if cp.has_option(url, 'aliases'): for i in cp.get(url, 'aliases').split(','): key = i.strip() @@ -843,7 +855,7 @@ def get_config(override_conffile = None, 'pass': password, 'http_headers': http_headers} - optional = ('email', 'sslcertck', 'cafile', 'capath') + optional = ('email', 'sslcertck', 'cafile', 'capath', 'login') for key in optional: if cp.has_option(url, key): if key == 'sslcertck': @@ -857,6 +869,9 @@ def get_config(override_conffile = None, if scheme == 'http': api_host_options[apiurl]['sslcertck'] = False + if auth_prot: + api_host_options[apiurl]['auth_prot'] = auth_prot + if cp.has_option(url, 'trusted_prj'): api_host_options[apiurl]['trusted_prj'] = cp.get(url, 'trusted_prj').split(' ') else: