More fixes for globalauth
parent
0a6f6a7a66
commit
b3000cf63b
|
@ -1,290 +0,0 @@
|
||||||
# -*-python-*-
|
|
||||||
# PythonHeaderParserHandler receiving Simple Global Authentication
|
|
||||||
# -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
from mod_python import apache, Cookie, util
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import struct
|
|
||||||
import cgi
|
|
||||||
import binascii
|
|
||||||
import time
|
|
||||||
import datetime
|
|
||||||
import urllib2
|
|
||||||
import anyjson
|
|
||||||
import random
|
|
||||||
|
|
||||||
import ga_config
|
|
||||||
|
|
||||||
if not ga_config.gac.get('globalauth_server','') and not ga_config.gac.get('fof_sudo_server',''):
|
|
||||||
raise Exception('ga_config.gac must contain at least globalauth_server="URL" or fof_sudo_server="URL"')
|
|
||||||
|
|
||||||
gac = {
|
|
||||||
'cookie_name' : 'simple_global_auth',
|
|
||||||
'cookie_expire' : 86400*7,
|
|
||||||
'cookie_path' : '/',
|
|
||||||
'cookie_domain' : '',
|
|
||||||
'globalauth_server' : '',
|
|
||||||
'cache_dir' : os.path.abspath(os.path.dirname(__file__))+'/cache',
|
|
||||||
'cut_email_at' : 0,
|
|
||||||
'ga_always_require' : 0,
|
|
||||||
'fof_sudo_server' : '',
|
|
||||||
'fof_sudo_cookie' : 'fof_sudo_id',
|
|
||||||
'gc_probability' : 20,
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in gac:
|
|
||||||
if ga_config.gac.get(i, None) is not None:
|
|
||||||
gac[i] = ga_config.gac[i]
|
|
||||||
|
|
||||||
def cachefn(key):
|
|
||||||
global gac
|
|
||||||
key = re.sub('([^a-zA-Z0-9_\-]+)', lambda x: binascii.hexlify(x.group(1)), key)
|
|
||||||
return gac['cache_dir']+'/'+key
|
|
||||||
|
|
||||||
def cacheclean():
|
|
||||||
global gac
|
|
||||||
t = time.time()
|
|
||||||
for fn in os.listdir(gac['cache_dir']):
|
|
||||||
if t > os.stat(gac['cache_dir']+'/'+fn).st_mtime:
|
|
||||||
os.unlink(gac['cache_dir']+'/'+fn)
|
|
||||||
|
|
||||||
def cacheset(key, value, expire = 86400):
|
|
||||||
fn = cachefn(key)
|
|
||||||
try:
|
|
||||||
f = open(fn,'w')
|
|
||||||
if not expire:
|
|
||||||
expire = 86400
|
|
||||||
expire = time.time()+expire
|
|
||||||
f.write(value)
|
|
||||||
f.close()
|
|
||||||
os.chmod(fn, 0600)
|
|
||||||
os.utime(fn, (expire, expire))
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def cacheget(key):
|
|
||||||
fn = cachefn(key)
|
|
||||||
try:
|
|
||||||
f = open(fn,'r')
|
|
||||||
value = f.read()
|
|
||||||
f.close()
|
|
||||||
if time.time() > os.stat(fn).st_mtime:
|
|
||||||
os.unlink(fn)
|
|
||||||
return ''
|
|
||||||
return value
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def cachedel(key):
|
|
||||||
fn = cachefn(key)
|
|
||||||
try:
|
|
||||||
os.unlink(fn)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
wd = { 0 : 'Mon', 1 : 'Tue', 2 : 'Wed', 3 : 'Thu', 4 : 'Fri', 5 : 'Sat', 6 : 'Sun' }
|
|
||||||
ms = { 1 : 'Jan', 2 : 'Feb', 3 : 'Mar', 4 : 'Apr', 5 : 'May', 6 : 'Jun', 7 : 'Jul', 8 : 'Aug', 9 : 'Sep', 10 : 'Oct', 11 : 'Nov', 12 : 'Dec' }
|
|
||||||
|
|
||||||
def setcookie(req, value):
|
|
||||||
global gac, wd, ms
|
|
||||||
exp = ''
|
|
||||||
dom = gac['cookie_domain']
|
|
||||||
if not dom:
|
|
||||||
dom = req.hostname
|
|
||||||
if gac['cookie_expire'] > 0:
|
|
||||||
tm = int(time.time()+gac['cookie_expire'])
|
|
||||||
tm = datetime.datetime.utcfromtimestamp(tm)
|
|
||||||
tm = "%s, %02d-%s-%04d %02d:%02d:%02d GMT" % (wd[tm.weekday()], tm.day, ms[tm.month], tm.year, tm.hour, tm.minute, tm.second);
|
|
||||||
exp = '; expires='+tm
|
|
||||||
req.headers_out.add('Set-Cookie', "%s=%s; path=%s; domain=%s%s" % (gac['cookie_name'], value, gac['cookie_path'], dom, exp))
|
|
||||||
|
|
||||||
def http_build_query(params, topkey = ''):
|
|
||||||
from urllib import quote
|
|
||||||
if len(params) == 0:
|
|
||||||
return ""
|
|
||||||
result = ""
|
|
||||||
if type (params) is dict:
|
|
||||||
for key in params.keys():
|
|
||||||
newkey = quote (key)
|
|
||||||
if topkey != '':
|
|
||||||
newkey = topkey + quote('[' + key + ']')
|
|
||||||
if type(params[key]) is dict:
|
|
||||||
result += http_build_query (params[key], newkey)
|
|
||||||
elif type(params[key]) is list:
|
|
||||||
i = 0
|
|
||||||
for val in params[key]:
|
|
||||||
result += newkey + quote('[' + str(i) + ']') + "=" + quote(str(val)) + "&"
|
|
||||||
i = i + 1
|
|
||||||
elif type(params[key]) is bool:
|
|
||||||
result += newkey + "=" + quote (str(int(params[key]))) + "&"
|
|
||||||
else:
|
|
||||||
result += newkey + "=" + quote (str(params[key])) + "&"
|
|
||||||
if (result) and (topkey == '') and (result[-1] == '&'):
|
|
||||||
result = result[:-1]
|
|
||||||
return result
|
|
||||||
|
|
||||||
def request_vars(req):
|
|
||||||
v = {}
|
|
||||||
if req.args:
|
|
||||||
v.update(util.parse_qs(req.args))
|
|
||||||
l = req.headers_in.get('Content-Length')
|
|
||||||
if l:
|
|
||||||
l = int(l)
|
|
||||||
if l and l > 0:
|
|
||||||
if req.headers_in.get('Content-Type').lower().find('multipart') >= 0:
|
|
||||||
v.update(cgi.parse_multipart(req, req.headers_in))
|
|
||||||
else:
|
|
||||||
c = ''
|
|
||||||
while len(c) < l:
|
|
||||||
c = c + req.read(l-len(c))
|
|
||||||
v.update(util.parse_qs(c))
|
|
||||||
#log("--REQUEST--")
|
|
||||||
for i in v:
|
|
||||||
if v[i].__class__.__name__ == 'list':
|
|
||||||
v[i] = v[i][0]
|
|
||||||
#log("REQUEST: "+i+"="+v[i])
|
|
||||||
return v
|
|
||||||
|
|
||||||
def log(s):
|
|
||||||
sys.stderr.write(s+"\n")
|
|
||||||
sys.stderr.flush()
|
|
||||||
|
|
||||||
def keydel(d, key):
|
|
||||||
try: del d[key]
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
def clean_uri(v, req):
|
|
||||||
uriargs = v.copy()
|
|
||||||
keydel(uriargs, 'ga_id')
|
|
||||||
keydel(uriargs, 'ga_res')
|
|
||||||
keydel(uriargs, 'ga_key')
|
|
||||||
keydel(uriargs, 'ga_client')
|
|
||||||
keydel(uriargs, 'ga_nologin')
|
|
||||||
keydel(uriargs, 'ga_require')
|
|
||||||
uri = 'http://'+req.hostname+req.uri+'?'+http_build_query(uriargs)
|
|
||||||
return uri
|
|
||||||
|
|
||||||
def set_env_user(req, r_data):
|
|
||||||
r_email = r_data.get('user_email', '').encode('utf-8')
|
|
||||||
r_url = r_data.get('user_url', '').encode('utf-8')
|
|
||||||
if gac['cut_email_at']:
|
|
||||||
p = r_email.find('@')
|
|
||||||
if p != -1:
|
|
||||||
r_email = r_email[0:p]
|
|
||||||
os.environ['REMOTE_USER'] = r_email
|
|
||||||
req.subprocess_env['REMOTE_USER'] = r_email
|
|
||||||
os.environ['user_url'] = r_url
|
|
||||||
req.subprocess_env['user_url'] = r_url
|
|
||||||
|
|
||||||
def globalauth_handler(req, jar, v):
|
|
||||||
global gac
|
|
||||||
i = random.randint(1, gac['gc_probability'])
|
|
||||||
if i == 1:
|
|
||||||
cacheclean()
|
|
||||||
r_id = jar.get(gac['cookie_name'], '')
|
|
||||||
if r_id:
|
|
||||||
r_id = r_id.value
|
|
||||||
ga_id = v.get('ga_id', '')
|
|
||||||
if ga_id!='' and v.get('ga_client','')!='':
|
|
||||||
ga_key = v.get('ga_key','')
|
|
||||||
if ga_key != '' and ga_key == cacheget('K'+ga_id):
|
|
||||||
cachedel('K'+ga_id)
|
|
||||||
data = ''
|
|
||||||
if v.get('ga_nologin','') != '':
|
|
||||||
data = 'nologin'
|
|
||||||
else:
|
|
||||||
try: data = anyjson.deserialize(v.get('ga_data',''))
|
|
||||||
except: raise
|
|
||||||
if data != '':
|
|
||||||
if data != 'nologin':
|
|
||||||
data = anyjson.serialize(data)
|
|
||||||
cacheset('D'+ga_id, data)
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_OK
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
|
|
||||||
elif ga_key == '' and r_id != ga_id:
|
|
||||||
d = cacheget('D'+ga_id)
|
|
||||||
if d != 'nologin' and d != '':
|
|
||||||
try: d = anyjson.deserialize(d)
|
|
||||||
except: d = ''
|
|
||||||
if d != '':
|
|
||||||
setcookie(req, ga_id)
|
|
||||||
util.redirect(req, clean_uri(v, req))
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_OK
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
|
|
||||||
r_data = ''
|
|
||||||
if r_id == 'nologin':
|
|
||||||
r_data = 'nologin'
|
|
||||||
elif r_id != '':
|
|
||||||
r_data = cacheget('D'+r_id)
|
|
||||||
if r_data != 'nologin':
|
|
||||||
try: r_data = anyjson.deserialize(r_data)
|
|
||||||
except: r_data = ''
|
|
||||||
if v.get('ga_client', '') == '' and (not r_data and (re.match('opera|firefox|chrome|safari', req.headers_in.get('User-Agent', ''), re.I) or gac['ga_always_require'])
|
|
||||||
or v.get('ga_require', '') != ''):
|
|
||||||
ga_id = binascii.hexlify(os.urandom(16))
|
|
||||||
ga_key = binascii.hexlify(os.urandom(16))
|
|
||||||
url = gac['globalauth_server']
|
|
||||||
if url.find('?') != -1:
|
|
||||||
url = url+'&'
|
|
||||||
else:
|
|
||||||
url = url+'?'
|
|
||||||
try:
|
|
||||||
resp = urllib2.urlopen(url+'ga_id='+urllib2.quote(ga_id)+'&ga_key='+urllib2.quote(ga_key))
|
|
||||||
resp.read()
|
|
||||||
if resp.code != 200:
|
|
||||||
raise Exception(resp)
|
|
||||||
except:
|
|
||||||
setcookie(req, 'nologin')
|
|
||||||
util.redirect(req, clean_uri(v, req))
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_OK
|
|
||||||
return_uri = 'http://'+req.hostname+req.uri+'?ga_client=1';
|
|
||||||
if req.args:
|
|
||||||
return_uri = return_uri+'&'+req.args
|
|
||||||
cacheset('K'+ga_id, ga_key)
|
|
||||||
url = url+'ga_id='+urllib2.quote(ga_id)+'&ga_url='+urllib2.quote(return_uri)
|
|
||||||
if v.get('ga_require', '') == '' and not gac['ga_always_require']:
|
|
||||||
url = url+'&ga_check=1'
|
|
||||||
util.redirect(req, url)
|
|
||||||
raise apache.SERVER_RETURN, apache.HTTP_OK
|
|
||||||
elif r_data and r_data != 'nologin':
|
|
||||||
set_env_user(req, r_data)
|
|
||||||
|
|
||||||
def fof_sudo_handler(req, jar, v):
|
|
||||||
global gac
|
|
||||||
sudo_id = jar.get(gac['fof_sudo_cookie'], '')
|
|
||||||
if sudo_id:
|
|
||||||
sudo_id = sudo_id.value
|
|
||||||
if sudo_id != '':
|
|
||||||
url = gac['fof_sudo_server']
|
|
||||||
if url.find('?') != -1:
|
|
||||||
url = url+'&'
|
|
||||||
else:
|
|
||||||
url = url+'?'
|
|
||||||
try:
|
|
||||||
resp = urllib2.urlopen(url+'id='+urllib2.quote(sudo_id))
|
|
||||||
d = resp.read()
|
|
||||||
if resp.code != 200:
|
|
||||||
raise Exception(resp)
|
|
||||||
d = anyjson.deserialize(d)
|
|
||||||
set_env_user(req, d)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def handler(req):
|
|
||||||
global gac
|
|
||||||
os.environ['REMOTE_USER'] = ''
|
|
||||||
req.subprocess_env['REMOTE_USER'] = ''
|
|
||||||
os.environ['user_url'] = ''
|
|
||||||
req.subprocess_env['user_url'] = ''
|
|
||||||
jar = Cookie.get_cookies(req)
|
|
||||||
v = request_vars(req)
|
|
||||||
if gac['fof_sudo_server'] != '':
|
|
||||||
fof_sudo_handler(req, jar, v)
|
|
||||||
if os.environ['REMOTE_USER'] == '' and gac['globalauth_server'] != '':
|
|
||||||
globalauth_handler(req, jar, v)
|
|
||||||
return apache.OK
|
|
|
@ -144,8 +144,6 @@ class GlobalAuthClient:
|
||||||
if r_id:
|
if r_id:
|
||||||
r_id = r_id.value
|
r_id = r_id.value
|
||||||
ga_id = self.v.get('ga_id', '')
|
ga_id = self.v.get('ga_id', '')
|
||||||
self.log('vars: '+anyjson.serialize(self.v))
|
|
||||||
self.log('ga_client? '+self.v.get('ga_client', ''))
|
|
||||||
if self.v.get('ga_client', ''):
|
if self.v.get('ga_client', ''):
|
||||||
self.ga_client(r_id, ga_id)
|
self.ga_client(r_id, ga_id)
|
||||||
return
|
return
|
||||||
|
@ -165,8 +163,6 @@ class GlobalAuthClient:
|
||||||
|
|
||||||
def ga_client(self, r_id, ga_id):
|
def ga_client(self, r_id, ga_id):
|
||||||
ga_key = self.v.get('ga_key', '')
|
ga_key = self.v.get('ga_key', '')
|
||||||
self.log('vars: '+anyjson.serialize(self.v))
|
|
||||||
self.log('s2s? '+ga_key+' '+self.cache.get('K'+ga_id))
|
|
||||||
if ga_key and ga_key == self.cache.get('K'+ga_id):
|
if ga_key and ga_key == self.cache.get('K'+ga_id):
|
||||||
# Server-to-server request
|
# Server-to-server request
|
||||||
self.cache.delete('K'+ga_id)
|
self.cache.delete('K'+ga_id)
|
||||||
|
@ -191,8 +187,7 @@ class GlobalAuthClient:
|
||||||
except: d = ''
|
except: d = ''
|
||||||
if d != '':
|
if d != '':
|
||||||
self.setcookie(ga_id)
|
self.setcookie(ga_id)
|
||||||
self.server.redirect(self.clean_uri())
|
self.redirect(self.clean_uri())
|
||||||
sys.exit()
|
|
||||||
self.server.header('text/plain', status=404)
|
self.server.header('text/plain', status=404)
|
||||||
self.server.write('GlobalAuth key doesn\'t match')
|
self.server.write('GlobalAuth key doesn\'t match')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
@ -208,16 +203,14 @@ class GlobalAuthClient:
|
||||||
raise Exception(resp)
|
raise Exception(resp)
|
||||||
except:
|
except:
|
||||||
self.setcookie('nologin')
|
self.setcookie('nologin')
|
||||||
self.server.redirect(self.clean_uri())
|
self.redirect(self.clean_uri())
|
||||||
sys.exit()
|
|
||||||
return_uri = 'http://'+self.server.getenv('HTTP_HOST')+self.server.getenv('REQUEST_URI')
|
return_uri = 'http://'+self.server.getenv('HTTP_HOST')+self.server.getenv('REQUEST_URI')
|
||||||
return_uri = self.add_param(return_uri, 'ga_client=1')
|
return_uri = self.add_param(return_uri, 'ga_client=1')
|
||||||
self.cache.set('K'+ga_id, ga_key)
|
self.cache.set('K'+ga_id, ga_key)
|
||||||
url = url+'ga_id='+urllib2.quote(ga_id)+'&ga_url='+urllib2.quote(return_uri)
|
url = url+'ga_id='+urllib2.quote(ga_id)+'&ga_url='+urllib2.quote(return_uri)
|
||||||
if self.v.get('ga_require', '') == '' and not self.gac['ga_always_require']:
|
if self.v.get('ga_require', '') == '' and not self.gac['ga_always_require']:
|
||||||
url = url+'&ga_check=1'
|
url = url+'&ga_check=1'
|
||||||
self.server.redirect(url)
|
self.redirect(url)
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
def add_param(self, url, param):
|
def add_param(self, url, param):
|
||||||
if url.find('?') != -1:
|
if url.find('?') != -1:
|
||||||
|
@ -250,10 +243,16 @@ class GlobalAuthClient:
|
||||||
sys.stderr.write(s+"\n")
|
sys.stderr.write(s+"\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
def redirect(self, url):
|
||||||
|
self.server.addheader('Location', url)
|
||||||
|
self.server.header(status='302 Moved Temporarily')
|
||||||
|
self.server.write('This document is located <a href="%s">here</a>.' % url)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
def setcookie(self, value):
|
def setcookie(self, value):
|
||||||
dom = self.gac['cookie_domain']
|
dom = self.gac['cookie_domain']
|
||||||
if not dom:
|
if not dom:
|
||||||
dom = server.getenv('HTTP_HOST')
|
dom = self.server.getenv('HTTP_HOST')
|
||||||
exp = ''
|
exp = ''
|
||||||
if self.gac['cookie_expire'] > 0:
|
if self.gac['cookie_expire'] > 0:
|
||||||
tm = int(time.time()+self.gac['cookie_expire'])
|
tm = int(time.time()+self.gac['cookie_expire'])
|
||||||
|
|
Loading…
Reference in New Issue