10 import os |
10 import os |
11 import os.path |
11 import os.path |
12 |
12 |
13 allowedchars = "A-Za-z0-9_-" |
13 allowedchars = "A-Za-z0-9_-" |
14 |
14 |
15 goodpathre = re.compile("([%s]+/)*[%s]+$" % (allowedchars, allowedchars)) |
|
16 def goodpath(path): |
|
17 return goodpathre.match(path) is not None |
|
18 |
|
19 goodglobre = re.compile("[*/%s]+$" % allowedchars) |
|
20 |
|
21 def goodglob(pattern): |
|
22 return goodglobre.match(pattern) is not None |
|
23 |
|
24 # Don't put anything except *A-Za-z0-9_- in rule globs or |
|
25 # it will match nothing. No regexp metachars, not even . |
|
26 # We may fix this later. |
|
27 def globmatcher(pattern): |
15 def globmatcher(pattern): |
28 if not goodglob(pattern): |
16 p = "[^/]*".join(re.escape(c) for c in pattern.split("*")) |
29 #fail("Bad glob pattern in auth config: %s" % pattern) |
17 # ** means "match recursively" ie "ignore directories" |
30 # FIXME: report it somehow |
18 rex = re.compile(p.replace("[^/]*[^/]*", ".*") + "$") |
31 return lambda x: False |
|
32 # Substitution cunning so ** can be different from * |
|
33 pattern = pattern.replace("*", "[]") |
|
34 pattern = pattern.replace("[][]", "[/%s]*" % allowedchars) |
|
35 pattern = pattern.replace("[]", "[%s]*" % allowedchars) |
|
36 rex = re.compile(pattern + "$") |
|
37 # None matches everything |
19 # None matches everything |
38 return lambda x: x is None or rex.match(x) is not None |
20 return lambda x: x is None or rex.match(x) is not None |
39 |
21 |
40 def rule(pairs): |
22 def rule(pairs): |
41 matchers = [(k, globmatcher(v)) for k, v in pairs] |
23 matchers = [(k, globmatcher(v)) for k, v in pairs] |
43 for k, m in matchers: |
25 for k, m in matchers: |
44 if k not in kw or not m(kw[k]): |
26 if k not in kw or not m(kw[k]): |
45 return False |
27 return False |
46 return True |
28 return True |
47 return c |
29 return c |
|
30 |
|
31 class AccessException(Exception): |
|
32 pass |
48 |
33 |
49 class Ruleset(object): |
34 class Ruleset(object): |
50 '''Class representing the rules in a rule file''' |
35 '''Class representing the rules in a rule file''' |
51 |
36 |
52 levels = ["init", "write", "read", "deny"] |
37 levels = ["init", "write", "read", "deny"] |
74 |
59 |
75 def allow(self, level, **kw): |
60 def allow(self, level, **kw): |
76 a = self.matchrule(kw) |
61 a = self.matchrule(kw) |
77 return a in self.levels and self.levels.index(a) <= self.levels.index(level) |
62 return a in self.levels and self.levels.index(a) <= self.levels.index(level) |
78 |
63 |
|
64 def check(self, level, **kw): |
|
65 if not self.allow(level, **kw): |
|
66 raise AccessException() |
|
67 |
79 def readfile(self, fn): |
68 def readfile(self, fn): |
80 try: |
69 try: |
81 f = open(fn) |
70 f = open(fn) |
82 try: |
71 try: |
83 for l in f: |
72 for l in f: |