1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
import re
from paste.httpheaders import CONTENT_TYPE
from paste.httpheaders import REQUEST_METHOD
from paste.httpheaders import USER_AGENT
from paste.request import construct_url
from repoze.who.interfaces import IRequestClassifier
import zope.interface
_DAV_METHODS = (
"OPTIONS",
"PROPFIND",
"PROPPATCH",
"MKCOL",
"LOCK",
"UNLOCK",
"TRACE",
"DELETE",
"COPY",
"MOVE",
)
_DAV_USERAGENTS = (
"Microsoft Data Access Internet Publishing Provider",
"WebDrive",
"Zope External Editor",
"WebDAVFS",
"Goliath",
"neon",
"davlib",
"wsAPI",
"Microsoft-WebDAV",
)
def my_request_classifier(environ):
"""Returns one of the classifiers 'dav', 'xmlpost', or 'browser',
depending on the imperative logic below"""
request_method = REQUEST_METHOD(environ)
if request_method in _DAV_METHODS:
return "dav"
useragent = USER_AGENT(environ)
if useragent:
for agent in _DAV_USERAGENTS:
if useragent.find(agent) != -1:
return "dav"
if request_method == "POST":
if CONTENT_TYPE(environ) == "text/xml":
return "xmlpost"
elif CONTENT_TYPE(environ) == "application/soap+xml":
return "soap"
return "browser"
zope.interface.directlyProvides(my_request_classifier, IRequestClassifier)
class MyChallengeDecider:
def __init__(self, path_login="", path_logout=""):
self.path_login = path_login
self.path_logout = path_logout
def __call__(self, environ, status, _headers):
if status.startswith("401 "):
return True
else:
if environ.has_key("samlsp.pending"):
return True
uri = environ.get("REQUEST_URI", None)
if uri is None:
uri = construct_url(environ)
# require and challenge for logout and inform the challenge plugin that it is a logout we want
for regex in self.path_logout:
if regex.match(uri) is not None:
environ["samlsp.logout"] = True
return True
# If the user is already authent, whatever happens(except logout),
# don't make a challenge
if environ.has_key("repoze.who.identity"):
return False
# require a challenge for login
for regex in self.path_login:
if regex.match(uri) is not None:
return True
return False
def make_plugin(path_login=None, path_logout=None):
if path_login is None:
raise ValueError("must include path_login in configuration")
# make regexp out of string passed via the config file
list_login = []
for arg in path_login.splitlines():
carg = arg.lstrip()
if carg != "":
list_login.append(re.compile(carg))
list_logout = []
if path_logout is not None:
for arg in path_logout.splitlines():
carg = arg.lstrip()
if carg != "":
list_logout.append(re.compile(carg))
plugin = MyChallengeDecider(list_login, list_logout)
return plugin
|